Handle every get or set call for objects

I am looking for a suitable approach for automatically checking permissions when accessing getter and setters properties.

This is just for curiosity and experimental purposes, so performance is not a big deal.

One approach I found is the following (example for getters only):

public class DynamicPropertyClass : DynamicObject
{
    /// <summary>
    /// I want this to work for a default auto-property
    /// </summary>
    public string TestString { get; set; }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (StaticSecurityContext.CheckSecurityCondition(binder.GetType(), binder.Name))
        {
            return base.TryGetMember(binder, out result);
        }
        else
        {
            throw new SecurityException();
        }
    }
}

Use a dynamic object to cancel if no security conditions are specified. The problem with this approach is that properties that actually exist in the class will not be processed by the TryGetMember method. Thus, this approach forces me to process properties that do not actually exist in the code.

, . , - , , .

, , #, ?

0
2

, , , DynamicProxy . DynamicProxy nuget Castle.Core.

Get Set .

Gist, ,   .

Interceptor.

public class GetSetInterceptor : Interceptor
{
    protected override void ExecuteBefore(IInvocation invocation)
    {
    }

    protected override void ExecuteAfter(IInvocation invocation)
    {
        if(invocation.Method.Name.StartsWith("get_") || invocation.Method.Name.StartsWith("set_"))
        {
            var target = invocation.InvocationTarget as TrackedObject;
            if(target == null)
            {
                return;
            }
            var methodInvoked = invocation.Method.Name.Split("_");
            switch (methodInvoked[0])
            {
                case "get":
                    target.AddEvent(EventType.Get, methodInvoked[1], invocation.ReturnValue);
                    break;
                case "set":
                    target.AddEvent(EventType.Set, methodInvoked[1], invocation.Arguments[0]);
                    break;
            }
        }
    }
}

- :

    ProxyGenerator generator = new ProxyGenerator();
    var tracked = generator.CreateClassProxy<TrackedClass>(new GetSetInterceptor());

TrackedClass :

public class TrackedClass : TrackedObject
{
    public virtual string SomeContent { get; set; }
    public virtual int SomeInt { get; set; }
}

( xUnit):

public class GetterSetterInterceptorTests
{
    [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);
    }
}
0

All Articles