当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Proxy class with overriden methods

问题描述:

In my .NET 4.0 application I'm accessing application properties through the interface ISettings I prepared:

public interface ISettings

{

int Quota { get; }

string Property2 { get; }

// ...

int PropertyN { get; }

}

// code generated by Visual Studio

public sealed partial class Settings :

global::System.Configuration.ApplicationSettingsBase

{

// application properties generated from app.config

[global::System.Configuration.ApplicationScopedSettingAttribute()]

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

[global::System.Configuration.DefaultSettingValueAttribute("123")]

public int Quota {

get {

return ((int)(this["Quota"]));

}

}

// and so on...

}

// my code to apply the interface to the Settings class

public sealed partial class Settings : ISettings

{

}

In some scenarios I would like to override the values from the config file depending on the organization I'm processing the data for, in example I would like to increase the quota for some organization. Of course, I could create the method similar to:

public int GetQuotaByOrgId(int orgId);

and implement the logic there, but I would like to avoid passing the orgId among the code. The better solution for me would be to create a proxy class overriding only the values I want to change, something like:

public class OverridenSettings : ISettings

{

private ISettings instance;

private int orgId;

private int[] orgsWithBiggerQuota = {1, 2, 132, 6542};

public OverridenSettings(ISettings instance, int orgId)

{

this.instance = instance;

this.orgId = orgId;

}

public override int Quota

{

get

{

int quota = this.instance.Quota;

if (this.orgsWithBiggerQuota.Contains(this.orgId))

{

quota += 1000;

}

return quota;

}

}

// all other properties should be taken from the default instance

}

Is there an elegant way to generate such class without having to explicitely implement all the interface's members just to redirect them to the default instance?

网友答案:

You can use any of the frameworks out there to create a dynamic proxy of your Settings class. For example using Unity I can create an object of a class(in your case Settings class) like this

ISettings settings = (ISettings)Intercept.NewInstance(typeof(Settings), new VirtualMethodInterceptor(), new IInterceptionBehavior[] { new OrganizationInterceptor(orgId)});

The OrganizationInterceptor has the ability to 'intercept' method calls(including property getters/setters) and could have an implementation like:

public class OrganizationInterceptor : IInterceptionBehavior
{
    private int OrgId { get; set; }
    private List<int> orgsWithBiggerQuota;

    public OrganizationInterceptor(int orgId)
    {
        OrgId = orgId;
        WillExecute = orgId > 0;
    }

    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        var ret = getNext()(input, getNext);

        if (input.MethodBase.IsSpecialName && input.MethodBase.Name == "get_Quota" &&
            this.orgsWithBiggerQuota.Contains(OrgId))
            ret.ReturnValue = (int)ret.ReturnValue + 100;

        return ret;
    }

    public bool WillExecute { get; set; }
}

I haven't ran this myself so you might need to debug it a bit(especially the Invoke method).

If you want to use the VirtualMethodInterceptor you need to declare your property virtual. There is also TransparentProxyInterceptor which doesnt require this but will create another object that will call into your object(2 objects in total vs 1 in the virtual case).

分享给朋友:
您可能感兴趣的文章:
随机阅读: