【问题标题】:Is it possible to add methods to classes with PostSharp? If yes, is it possible to then reference those methods from other classes?是否可以使用 PostSharp 向类添加方法?如果是,是否可以从其他类中引用这些方法?
【发布时间】:2011-07-04 02:08:23
【问题描述】:

假设我有一堂课Abc:

class Abc {
}

我想在外部添加一些方法m()。我想这可能是可能的,虽然我不知道怎么做。假设可以这样做,那么假设 Abc 从现在开始确实有一个 m() 方法。

现在,假设我还有其他课程Def:

class Def {
    public void x(Abc abc) {
        abc.m();
    }
}

此代码是否可以与 PostSharp 一起运行?对于分心的读者来说,这样做的问题是,在标准的 C# 类程序中,我们的编译器可能不知道 Abc 类有一个 m() 方法。

我的直觉是这不适用于 PostSharp。我弄错了吗?

【问题讨论】:

  • 更新了我的答案,包括 2 种介绍方法的方法。

标签: c# postsharp aop


【解决方案1】:

(如果我的 PostSharp 解决方案不够用,也许您可​​以使用 DLR 来完成?)

是的,你可以。您将在实例范围方面使用引入成员属性。您最好的选择是使用 postshsrp 实现一个接口,然后将您的目标类引用为该接口以公开该方法。您还可以在设计时使用 Post.Cast() 来访问它。

这里有两种方法可以做到这一点。第一种是通过接口,第二种是使用存根。

方法 1 - 接口

public class Program
    {
        static void Main(string[] args)
        {
            Customer c = new Customer();
            var cc = Post.Cast<Customer, ISomething>(c);

            cc.SomeMethod();
        }
    }

    public interface ISomething
    {
        void SomeMethod();
    }

    [AddMethodAspect]
    public class Customer
    {

    }

    [Serializable]
    [IntroduceInterface(typeof(ISomething))]
    public class AddMethodAspect : InstanceLevelAspect, ISomething
    {

        #region ISomething Members

        public void SomeMethod()
        {
            Console.WriteLine("Hello");
        }

        #endregion
    }

方法 2 - 存根

public class Program
    {
        static void Main(string[] args)
        {
            Customer c = new Customer();
            c.SomeMethod();
        }
    }

    [AddMethodAspect]
    public class Customer
    {
        public void SomeMethod() { }

    }

    [Serializable]
    public class AddMethodAspect : InstanceLevelAspect
    {
        [IntroduceMember(OverrideAction = MemberOverrideAction.OverrideOrFail)]
        public void SomeMethod()
        {
            Console.WriteLine("Hello");
        }
    }

更多信息 以防万一使用 Cast() 函数出现一些问题,它不会进行实际的转换。编译结果如下:

private static void Main(string[] args)
        {
            Customer c = new Customer();
            ISomething cc = c;
            cc.SomeMethod();
        }

【讨论】:

    【解决方案2】:

    如果该类在不同的程序集中,您可以这样做。

    另一方面,如果类在同一个模块中,那么你是对的,C# 编译器不会编译它。为什么不在 C# 中像这样实现m(),然后用 PostSharp 替换实现?

    class Abc
    {
       public void m()
       {
          throw new NotImplementedException ();
       }
    }
    

    编辑:

    如果您将m() 放在一个接口中,然后使用 PostSharp 在您的类上实现该接口会怎样?然后,您可以通过转换为该接口来调用该方法。

    interface IM
    {
       void m();
    }
    
    class Def {
        public void x(Abc abc) {
           if (abc is IM)
            ((IM) abc).m();
        }
    }
    

    【讨论】:

    • 因为这样就违背了我的横切关注点仅在方面而不是在类本身中的整个目的!添加/删除关注点将意味着必须更改所有类。
    • 如果你直接调用一个方法,你如何横切关注点?如果您将m() 放在一个接口中,然后使用 PostSharp 在您的类上实现该接口怎么办?然后,您可以通过转换为该接口来调用该方法。
    • 我看不出从某个方面调用方法有什么问题。想象一下 ApplyBonus 方面,它具有银行系统中与奖金相关的所有逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 2021-12-06
    • 2016-09-05
    • 2018-05-21
    • 1970-01-01
    • 2012-08-05
    • 2023-04-03
    相关资源
    最近更新 更多