【问题标题】:Using Castle to create AOP with a 3rd party IoC使用 Castle 使用第 3 方 IoC 创建 AOP
【发布时间】:2018-08-10 19:35:21
【问题描述】:

我正在尝试使用面向方面的编程。问题是内部有一个定制的 IoC 不支持这种类型的编程。我把问题分解成最重要的部分。我正在使用城堡来实现 AOP。这些问题在代码 cmets 中进行了描述。

我认为我不能这样做,因为泛型是在编译时就被知道的。但是,我希望社区可以比我聪明。

更新 2 - 更新为工作代码(感谢 @vasiloreshenski)

using Castle.DynamicProxy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

namespace Tests.Component.CastleTests
{
    [TestClass]
    public class GenericTest
    {
        [TestMethod]
        public void TestGeneric()
        {
            IMyPoco mypoco = ContrivedCustomIoc.Create<IMyPoco>();
            mypoco.DoWorkNoLogging();
            mypoco.DoWork();
            //Assert.IsTrue(typeof(MyPoco) == mypoco.GetType());
        }
    }

    public class ContrivedCustomIoc
    {
        private static Dictionary<string, string> mappings = new Dictionary<string, string>();

        static ContrivedCustomIoc()
        {
            //This comes from XML file
            mappings.Add("Tests.Component.CastleTests.IMyPoco", "Tests.Component.CastleTests.MyPoco");
        }

        public static T Create<T>() where T : class
        {
            string contractType = typeof(T).FullName;
            Type thisTypeInterface = Type.GetType(contractType);
            Type thisTypeConcrete = Type.GetType(mappings[contractType]);

            //Things work up until this point just fine
            //return (T)Activator.CreateInstance(thisTypeConcrete);


            var generator = new Castle.DynamicProxy.ProxyGenerator();
            //ERROR.  Class to proxy must be a class.
            //This is because T is an interface
            //Is it possible to use Castle with this custom IoC?  I want to avoid replacing the entire IoC 
            //I'd like to simply get an aspect oriented programming pattern in place
            //return generator.CreateClassProxy<T>(new MyLoggingInterceptor());

            object result = generator.CreateClassProxy(thisTypeConcrete, ProxyGenerationOptions.Default,
                new IInterceptor[1] { new MyLoggingInterceptor() });

            return (T) result;
        }
    }

    public interface IMyPoco
    {
        void DoWorkNoLogging();
        void DoWork();
    }

    public class MyPoco : IMyPoco
    {
        public void DoWorkNoLogging()
        {
            Console.Write(("Work bein done without logging"));
        }

        public virtual void DoWork()
        {
            Console.WriteLine("Work bein done!");
        }
    }

    public class MyLoggingInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            try
            {
                Console.WriteLine("Interceptor starting");
                invocation.Proceed();
                Console.WriteLine("Interceptor ending");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                Console.WriteLine("Exiting from interceptor");
            }
        }
    }
}

【问题讨论】:

  • 您不能在 C# 中创建接口的实例。
  • 有一个从运行时类型创建代理的重载,在你的情况下这将是'thisTypeConcrete',那么你只需要转换回T。检查docs.stumme.net/Castle.Core/html/…
  • @vasiloreshenski - 我认为你在正确的轨道上。对象按应有的方式创建。但是没有调用拦截器。如果是的话,你会完全回答这个问题的!
  • @P.Brian.Mackey 只有当您创建代理的类具有任何虚拟方法时,才会执行拦截调用。尝试在 MyPoco 中定义虚拟方法,看看这是否会改变任何东西......
  • @vasiloreshenski - 是的,我忘了!有用!非常感谢。如果您发布答案只是告诉我您在此处所说的内容,我会很乐意为您提供答案。

标签: c# castle-dynamicproxy


【解决方案1】:

注意:这是导致成功调用拦截器的 cmets 的摘要。

  1. 使用接受运行时类型的caste proxy generator 的重载。
  2. 为了执行拦截器,您需要在要拦截的类实现中使用虚拟方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多