C# unity 通过属性拦截

2023-11-24

有没有办法在 C# unity 中使用属性拦截并将对象注册代码保留在 XML 文件(如 app.config)中?如果是的话,您能给我提供代码吗?这样的注册应该是什么样子?我做了很多解决方法,但没有找到解决此问题的有效解决方案。


我假设您的意思是使用自定义属性来指示要拦截的方法。您可以使用策略注入来通过XML配置来实现拦截。

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

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

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

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; }
}

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

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!");
    }
}

请注意,我已将自定义属性 MyInterception 仅应用于 Do 方法,而不应用于 DoAgain 方法。我们将拦截对 Do 方法的所有调用。

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

<?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>

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

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;
    }
}

一旦我们完成所有设置,我们就可以创建一个容器并加载配置:

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

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

输出将是:

Invoking Do
Do!
Done Invoke
Do Again!

显示第一个方法被拦截,而第二个方法没有被拦截。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# unity 通过属性拦截 的相关文章

随机推荐