Dynamically generate getter / setter property via reflection or similar

Imagine the following class:

public class Settings
{
    [FileBackedProperty("foo.txt")]
    public string Foo { get; set; }
}

I would like to write something similar to the previous one and settings.Fooread from the file "foo.txt" and settings.Foo = "bar"write in "foo.txt".

Obviously, this is a simplified example, and I would not have done it in a production application, but there are other examples, for example, if I wanted Foo to be stored in the ASP.net "foo" session state, but I'm tired of repeating the following code :

public int Foo
{
    get
    {
        if (Session["foo"] != null)
            return Convert.ToInt32(Session["foo"]);
        else
            // Throw an exception or return a default value
    }
    set
    {
        Session["foo"] = value;
    }
}

(Once again, this example is simplified, and I would not have written the code above, in fact I lie, I have the code above and I am working to reorganize it, thus this question)

, 50 , . - - ? ( , , , ?)

+5
6

, , ( ) ; , . get & set GetProperty GetCustomAttributes , get & set static . , , , (:

. , .

public class SampleClass : SessionObject
{
    [Session(Key = "SS_PROP")]
    public virtual int SampleProperty
    {
        get { return get(); }
        set { set(value); }
    }

    [Session(Key = "SS_PROP2")]
    public virtual string SampleProperty2
    {
        get { return get(); }
        set { set(value); }
    }
}

[AttributeUsage(AttributeTargets.Property)]
public class SessionAttribute : Attribute
{
    public string Key { get; set; }
}

public abstract class SessionObject
{
    Dictionary<string, object> Session = new Dictionary<string, object>();

    protected void set(object value)
    {
        StackFrame caller = new StackFrame(1);
        MethodBase method = caller.GetMethod();
        string propName = method.Name.Substring(4);
        Type type = method.ReflectedType;
        PropertyInfo pi = type.GetProperty(propName);
        object[] attributes = pi.GetCustomAttributes(typeof(SessionAttribute), true);
        if (attributes != null && attributes.Length == 1)
        {
            SessionAttribute ssAttr = attributes[0] as SessionAttribute;
            Session[ssAttr.Key] = value;
        }
    }

    protected dynamic get()
    {
        StackFrame caller = new StackFrame(1);
        MethodBase method = caller.GetMethod();
        string propName = method.Name.Substring(4);
        Type type = method.ReflectedType;
        PropertyInfo pi = type.GetProperty(propName);
        object[] attributes = pi.GetCustomAttributes(typeof(SessionAttribute), true);
        if (attributes != null && attributes.Length == 1)
        {
            SessionAttribute ssAttr = attributes[0] as SessionAttribute;
            if (Session.ContainsKey(ssAttr.Key))
            {
                return Session[ssAttr.Key];
            }
        }
        return default(dynamic);
    }
}
+4

PostSharp. IL , . .

.

.

, .

+3

, :

public int Foo
{
    get
    {
        return GetHelper<int>("foo");
    }
    set
    {
        Session["foo"] = value;
    }
}

public T GetHelper<T>(string name, T defaultValue = default(T))
{
    if (Session[name] != null)
        return (T)Session[name];
    else
    {
        return defaultValue;
    }
}

, :

internal class DynamicSession : DynamicObject
{
    private HttpSessionState_session;

    public DynamicSession()
    {
        _session = HttpContext.Current.Session;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (_session[binder.Name] != null)
        {
            result = _session[binder.Name];
            return true;
        }
        result = null;
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _session[binder.Name] = value;
        return true;
    }
}

:

dynamic session = new DynamicSession();
    //These properties are "magically" put in and taken out of session!
//get
int foo = session.Foo;
//set
session.Foo = 3;

- - Live Templates Resharper, .

+1
+1

, , "- ", , . , , .

: , . "" CLR, , .

, ; , , MarshallByRefObject ContextBoundObject; 10- , .

: http://www.developerfusion.com/article/5307/aspect-oriented-programming-using-net/3/

Dynamic Proxies " " , . , - # , ORM, IoC framework .. .. - Castle DynamicProxy , , , / .

+1

DynamicProxy nuget Castle.Core .

You can intercept calls for Get and Set methods for all virtual properties of your class. However, all getters and setters that you want to change must be virtual.

I gave a more complete answer here: fooobar.com/questions/1108713 / ... and is now available here .

The following behavior should be observed:

    [Fact]
    public void SuccessFullyRegisterGetAndSetEvents()
    {
        ProxyGenerator generator = new ProxyGenerator();
        var tracked = generator.CreateClassProxy<TrackedClass>(new GetSetInterceptor());
        tracked.SomeContent = "some content";
        Assert.Single(tracked.GetEvents());
        var eventAfterSomeContentAssigned = tracked.GetEvents().Last();
        Assert.Equal(EventType.Set, eventAfterSomeContentAssigned.EventType);
        Assert.Equal("some content", eventAfterSomeContentAssigned.Value);
        Assert.Equal("SomeContent", eventAfterSomeContentAssigned.PropertyInfo.Name);
        tracked.SomeInt = 1;
        Assert.Equal(2, tracked.GetEvents().Count);
        var eventAfterSomeIntAssigned = tracked.GetEvents().Last();
        Assert.Equal(EventType.Set, eventAfterSomeContentAssigned.EventType);
        Assert.Equal(1, eventAfterSomeIntAssigned.Value);
        Assert.Equal("SomeInt", eventAfterSomeIntAssigned.PropertyInfo.Name);
        var x = tracked.SomeInt;
        Assert.Equal(3, tracked.GetEvents().Count);
        var eventAfterSomeIntAccessed = tracked.GetEvents().Last();
        Assert.Equal(EventType.Get, eventAfterSomeIntAccessed.EventType);
        Assert.Equal(1, eventAfterSomeIntAccessed.Value);
        Assert.Equal("SomeInt", eventAfterSomeIntAccessed.PropertyInfo.Name);
    }

Hope this helps.

0
source

All Articles