Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Castle与第三方IoC创建AOP_C#_Castle Dynamicproxy - Fatal编程技术网

C# 使用Castle与第三方IoC创建AOP

C# 使用Castle与第三方IoC创建AOP,c#,castle-dynamicproxy,C#,Castle Dynamicproxy,我正在尝试使用面向方面编程。问题是,有一个定制的内部IoC不支持这种类型的编程。我把问题分解成最重要的部分。我正在使用castle实现AOP。代码注释中描述了这些问题 我不认为我能做到这一点,因为泛型应该在编译时被知道。然而,我希望社区能比我聪明 更新2-更新为工作代码(这要感谢@vasiloreshenski) 使用Castle.DynamicProxy; 使用Microsoft.VisualStudio.TestTools.UnitTesting; 使用制度; 使用System.Collec

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

我不认为我能做到这一点,因为泛型应该在编译时被知道。然而,我希望社区能比我聪明

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

使用Castle.DynamicProxy;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用制度;
使用System.Collections.Generic;
命名空间Tests.Component.CastleTests
{
[测试类]
公共类通用测试
{
[测试方法]
公共void TestGeneric()
{
IMyPoco mypoco=ContrivedCustomIoc.Create();
mypoco.doorknologging();
mypoco.DoWork();
//Assert.IsTrue(typeof(MyPoco)=MyPoco.GetType());
}
}
公共类
{
私有静态字典映射=新字典();
静态ContrivedCustomIoc()
{
//这来自XML文件
Add(“Tests.Component.CastleTests.IMyPoco”、“Tests.Component.CastleTests.MyPoco”);
}
公共静态T Create(),其中T:class
{
string contractType=typeof(T).FullName;
键入ThistTypeInterface=Type.GetType(contractType);
键入ThistTypeConcrete=Type.GetType(映射[contractType]);
//到目前为止一切正常
//return(T)Activator.CreateInstance(thisTypeConcrete);
var generator=newcastle.DynamicProxy.ProxyGenerator();
//错误。要代理的类必须是类。
//这是因为T是一个接口
//是否可以将Castle与此自定义IoC一起使用?我希望避免替换整个IoC
//我只想建立一个面向方面的编程模式
//返回generator.CreateClassProxy(新的MyLoggingInterceptor());
对象结果=generator.CreateClassProxy(thisTypeConcrete,ProxyGenerationOptions.Default,
新的IInterceptor[1]{new MyLoggingInterceptor()});
返回(T)结果;
}
}
公共接口IMyPoco
{
void doworknoogging();
无效销钉();
}
公共类MyPoco:IMyPoco
{
公共无效DoWorkNoLogging()
{
Console.Write((“没有记录就完成了工作”);
}
公共虚拟空工作()
{
Console.WriteLine(“工作完成了!”);
}
}
公共类MyLoggingInterceptor:IInterceptor
{
公共无效拦截(IInvocation调用)
{
尝试
{
控制台写入线(“拦截器启动”);
invocation.procedure();
控制台写入线(“截取器结束”);
}
捕获(例外e)
{
控制台写入线(e);
投掷;
}
最后
{
控制台写入线(“从拦截器退出”);
}
}
}
}

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

  • 使用接受运行时类型的重载
  • 为了执行拦截器,需要截获类实现中的虚拟方法

  • 您不能在C#中创建接口实例。有一个重载从运行时类型创建代理,在您的情况下,这将是“thisTypeConcrete”,然后您只需要返回到t。检查@vasiloreshenski-我认为您走对了方向。对象的创建方式与应该的一样。但是,没有调用拦截器。如果是的话,你会完全回答这个问题的@P.Brian.Mackey仅当创建代理的类具有任何虚拟方法时,才会执行拦截调用。尝试在MyPoco中定义虚拟方法,看看这是否会改变什么…@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");
                }
            }
        }
    }