按属性C#团结拦截 [英] c# unity interception by attribute

查看:150
本文介绍了按属性C#团结拦截的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是这里的路该怎么按属性在C#中使用统一的拦截和保持对象注册代码的XML文件(如app.config)中?如果是的话,你能为我提供的代码,应该如何注册等看?我做了很多workarround,但没有找到这个问题的一些工作解决方案。


解决方案

我假设你的意思是使用自定义属性来表示什么方法拦截。您可以使用策略注射使用XML配置来实现拦截



首先,让我们定义一个自定义属性:

  [AttributeUsage(AttributeTargets.Method)
公共类MyInterceptionAttribute:属性
{
}

接下来,我们可以创建一个ICallHandler做一些拦截工作。在此之前实现将只是做一个Console.WriteLine和方法后:

 公共类MyLoggingCallHandler:ICallHandler 
$ { b $ b IMethodReturn ICallHandler.Invoke(IMethodInvocation输入,GetNextHandlerDelegate GETNEXT)
{
Console.WriteLine(调用+ input.MethodBase.Name);
IMethodReturn结果= GETNEXT()(输入,GETNEXT);
Console.WriteLine(完成调用);
返回结果;
}

INT ICallHandler.Order {搞定;组; }
}



接下来让我们假设我们有一些接口和一个实现:

 公共接口IMyClass 
{
无效DO();
无效DoAgain();
}

公共MyClass类:IMyClass
{
[MyInterception]
公共无效DO()
{
控制台。的WriteLine(做!);
}

公共无效DoAgain()
{
Console.WriteLine(再做!);
}
}

这是我申请的自定义属性通知,MyInterception ,只该做的方法,但不是DoAgain方法。我们将截取到待办事项方法的调用



接下来,我们创建配置定义策略,配置匹配规则,并用拦截器一起注册类型:



<预类=郎咸平的XML prettyprint-覆盖> <?XML版本=1.0>?;
<结构>
< configSections>
<节名称=团结TYPE =Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration/>
< / configSections>
<统一的xmlns =http://schemas.microsoft.com/practices/2010/unity>
<命名空间名称=UnityCallHandlerConfig/>
<装配NAME =UnityCallHandlerConfig/>
< sectionExtension TYPE =Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,Microsoft.Practices.Unity.Interception.Configuration/>
<集装箱>
<外延式=堵/>
<&拦截GT;
<策略名称=政策>
<匹配规则名称=匹配TYPE =Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule,Microsoft.Practices.Unity.Interception>
<&构造GT;
< PARAM NAME =属性类型值=UnityCallHandlerConfig.MyInterceptionAttribute,UnityCallHandlerConfig的TypeConverter =AssemblyQualifiedTypeNameConverter/>
< PARAM NAME =继承>
<值值=FALSE/>
< /参数>
< /构造>
< /匹配规则>
< callHandler NAME =MyLoggingTYPE =MyLoggingCallHandler>
<终身TYPE =单身/>
< / callHandler>
< /政策与GT;
< /拦截>
<注册类型=IMyClassmapTo =MyClass的>
<拦截TYPE =InterfaceInterceptor/>
< interceptionBehavior TYPE =PolicyInjectionBehavior/>
< /注册>
< /容器>
< /统一性GT;

<&启动GT;
< supportedRuntime版本=V4.0SKU =.net框架,版本= V4.5/>
< /启动>
< /结构>

我们还需要一个类型转换器的自定义属性的正确类型的字符串表示形式转换:

 公共类AssemblyQualifiedTypeNameConverter:ConfigurationConverterBase 
{
公众覆盖对象的ConvertTo(ITypeDescriptorContext背景下,System.Globalization.CultureInfo文化,对象的值,类型destinationType)
{
如果(值= NULL)
{
型typeValue =值类型!;
如果(typeValue == NULL)
{
抛出新的ArgumentException(无法将类型,typeof运算(类型).Name点);
}

如果(typeValue!= NULL)回报(typeValue).AssemblyQualifiedName;
}
返回NULL;
}

公共覆盖对象ConvertFrom(ITypeDescriptorContext背景下,System.Globalization.CultureInfo文化,对象的值)
{
串stringValue的=(字符串)值;
如果
{
型结果= Type.GetType(stringValue的,假)(string.IsNullOrEmpty(stringValue的)!);
如果(结果== NULL)
{
抛出新的ArgumentException(无效型,值);
}

返回结果;
}
返回NULL;
}
}



一旦我们拥有所有的设置,我们可以创建一个集装箱装载配置:

  VAR集装箱=新UnityContainer()LoadConfiguration(); 

VAR MyClass的= container.Resolve< IMyClass>();
myClass.Do();
myClass.DoAgain();

输出将是:



 待办事项中调用
执行!
做调用
再做!



示出,而第二不是第一方法被截取


is here a way how to use interception by attribute in c# unity and keep the object registration code in xml file(like app.config)? If yes can you provide me with code, how should such registration look? I did a lot of workarround but did not find some working solution for this issue.

解决方案

I'm assuming you mean using a custom attribute to indicate what methods to intercept. You can use policy injection to achieve interception using XML configuration.

First, let's define a custom attribute:

[AttributeUsage(AttributeTargets.Method)]
public class MyInterceptionAttribute : Attribute
{
}

Next we can create an ICallHandler to do some interception work. This implementation will just do a Console.WriteLine before and after the method:

public class MyLoggingCallHandler : ICallHandler
{
    IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Console.WriteLine("Invoking " + input.MethodBase.Name);
        IMethodReturn result = getNext()(input, getNext);
        Console.WriteLine("Done Invoke");
        return result;
    }

    int ICallHandler.Order { get; set; }
}

Next let's assume that we have some interface and an implementation:

public interface IMyClass
{
    void Do();
    void DoAgain();
}

public class MyClass : IMyClass 
{
    [MyInterception]
    public void Do()
    {
        Console.WriteLine("Do!");
    }

    public void DoAgain()
    {
        Console.WriteLine("Do Again!");
    }
}

Notice that I've applied the custom attribute, MyInterception, to only the Do method but not the DoAgain method. We will intercept all calls to the Do method.

Next we create the configuration to define a policy, configure the matching rule and register the type along with an interceptor:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace name="UnityCallHandlerConfig" />
    <assembly name="UnityCallHandlerConfig"  />
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
    <container>
      <extension type="Interception"/>
      <interception>
        <policy name="Policy">
          <matchingRule name="Match" type="Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule, Microsoft.Practices.Unity.Interception">
            <constructor>
              <param name="attributeType" value="UnityCallHandlerConfig.MyInterceptionAttribute, UnityCallHandlerConfig" typeConverter="AssemblyQualifiedTypeNameConverter" />
              <param name="inherited">
                <value value="false"/>
              </param>
            </constructor>
          </matchingRule>
          <callHandler name="MyLogging" type="MyLoggingCallHandler">
            <lifetime type="singleton"/>
          </callHandler>
        </policy>
      </interception>
      <register type="IMyClass" mapTo="MyClass">
        <interceptor type="InterfaceInterceptor"/>
        <interceptionBehavior type="PolicyInjectionBehavior"/>
      </register>
    </container>
  </unity>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
  </startup>
</configuration>

We also need a type converter to convert the string representation of the custom attribute to the proper type:

public class AssemblyQualifiedTypeNameConverter : ConfigurationConverterBase
{
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (value != null)
        {
            Type typeValue = value as Type;
            if (typeValue == null)
            {
                throw new ArgumentException("Cannot convert type", typeof(Type).Name);
            }

            if (typeValue != null) return (typeValue).AssemblyQualifiedName;
        }
        return null;
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        string stringValue = (string)value;
        if (!string.IsNullOrEmpty(stringValue))
        {
            Type result = Type.GetType(stringValue, false);
            if (result == null)
            {
                throw new ArgumentException("Invalid type", "value");
            }

            return result;
        }
        return null;
    }
}

Once we have all that set up we can create a container and load the configuration:

var container = new UnityContainer().LoadConfiguration();

var myClass = container.Resolve<IMyClass>();
myClass.Do();
myClass.DoAgain();

The output will be:

Invoking Do
Do!
Done Invoke
Do Again!

showing that the first method is intercepted while the second is not.

这篇关于按属性C#团结拦截的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆