首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >可以运行在不遵循CA1033的基类中显式实现的代码。

可以运行在不遵循CA1033的基类中显式实现的代码。
EN

Code Review用户
提问于 2015-06-18 12:21:10
回答 1查看 387关注 0票数 4

有时,当使用库供应商(如DevExpress )创建的组件时,您希望扩展这些组件。好的供应商将为您留下大量的虚拟方法供您使用,但有时您需要连接到显式实现该方法的类中的接口方法调用。您可以简单地重新实现接口方法,但是10次中有9次您仍然希望调用基本实现,就好像它是虚拟的一样。事实上,CA1033(它应该是虚拟的)

同时,基本实现是私有的,您需要使用反射。这个类减轻了一些麻烦,这样您就不必提交反射代码了。它为您提供了一个实现接口的对象,该对象直接调用私有的基本实现方法。

一个例子值得一千种解释:

代码语言:javascript
运行
复制
interface IExampleInterface
{
    string InterfaceMethod();
}

class BaseClass : IExampleInterface
{
    // The authors of BaseClass did not follow CA1033: Interface methods should be callable by child types
    string IExampleInterface.InterfaceMethod()
    {
        return "BaseClass implementation";
    }
}

sealed class CustomizedClass : BaseClass, IExampleInterface
{
    // We have no choice but to override by implementing the method.
    string IExampleInterface.InterfaceMethod()
    {
        // Now in order to access the base explicit implementation, we use the class below:
        return LanguageUtils.ExplicitImplementation<BaseClass, IExampleInterface>(this).InterfaceMethod() + " has been customized.";
    }
}

令人惊讶的是,几乎没有任何代码:

代码语言:javascript
运行
复制
public static class LanguageUtils
{
    public static TInterface ExplicitImplementation<TBase, TInterface>(TBase @this)
        where TBase : TInterface
        where TInterface : class
    {
        return (TInterface)new ExplicitImplementationProxy(typeof(TBase), @this).GetTransparentProxy();
    }

    private sealed class ExplicitImplementationProxy : RealProxy, IRemotingTypeInfo
    {
        private readonly Type baseType;
        private readonly object instance;

        public ExplicitImplementationProxy(Type baseType, object instance) : base(typeof(MarshalByRefObject))
        {
            this.baseType = baseType;
            this.instance = instance;
        }

        public bool CanCastTo(Type fromType, object o)
        {
            return fromType.IsInterface && fromType.IsAssignableFrom(baseType);
        }

        public string TypeName { get; set; }

        public override IMessage Invoke(IMessage msg)
        {
            var methodCall = msg as IMethodCallMessage;
            if (methodCall == null) throw new NotSupportedException();

            var map = baseType.GetInterfaceMap(methodCall.MethodBase.DeclaringType);
            var args = new object[methodCall.Args.Length];
            Array.Copy(methodCall.Args, args, args.Length);
            return new ReturnMessage(map.TargetMethods[Array.IndexOf(map.InterfaceMethods, (MethodInfo)methodCall.MethodBase)].Invoke(instance, args), args, args.Length, methodCall.LogicalCallContext, methodCall);
        }
    }
}
EN

回答 1

Code Review用户

发布于 2015-11-05 19:37:32

这是一个相当整洁的实现,这里没什么可说的。一对非常未成年的人:

  1. 这有点难读:返回新的ReturnMessage(.Invoke,args)、args、args.Length、methodCall.LogicalCallContext、methodCall;我将其拆分为: var targetMethod = map.TargetMethodsArray.IndexOf(map.InterfaceMethods,(MethodInfo)methodCall.MethodBase);返回新ReturnMessage(例如,args)、args、args.Length、methodCall.LogicalCallContext、methodCall;
  2. 克隆参数数组,而不是显式复制它: var args = (object[])methodCall.Args.Clone();以更紧凑的方式表示语义。
  3. 对我来说,这似乎是一种转发方法,所以我可能会考虑将其重命名,并可能将其转换为扩展方法(我喜欢它的语法优势)。类似于这样的内容:公共静态TInterface ForwardToBase(this TBase @this),其中TBase : TInterface TBase TInterface : class { read (TInterface)新ExplicitImplementationProxy(typeof(TBase),@this).GetTransparentProxy();}在这种情况下,调用将读为: this.ForwardToBase().InterfaceMethod()
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/93976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档