2013-06-13 33 views
7

Có cách nào để sử dụng đánh chặn bằng thuộc tính trong C# unity và giữ mã đăng ký đối tượng trong tệp XML (như app.config) không? Nếu có, bạn có thể cung cấp mã cho tôi không, đăng ký như thế nào? Tôi đã làm rất nhiều cách giải quyết nhưng không tìm thấy một số giải pháp làm việc cho vấn đề này.C# unity interception bởi thuộc tính

Trả lời

14

Tôi giả sử bạn ngụ ý sử dụng thuộc tính tùy chỉnh để chỉ ra phương pháp chặn nào. Bạn có thể sử dụng chính sách tiêm để đạt được đánh chặn bằng cách sử dụng cấu hình XML.

Trước tiên, hãy xác định một thuộc tính tùy chỉnh:

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

Tiếp theo chúng ta có thể tạo ra một ICallHandler để làm một số công việc đánh chặn. thực hiện điều này sẽ chỉ làm một Console.WriteLine trước và sau khi phương pháp:

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

Tiếp theo chúng ta hãy giả sử rằng chúng ta có một số giao diện và một thực hiện:

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

Chú ý rằng tôi đã áp dụng các thuộc tính tùy chỉnh , MyInterception, chỉ với phương thức Do chứ không phải phương thức DoAgain. Chúng tôi sẽ chặn tất cả các cuộc gọi đến phương thức Do.

Tiếp theo chúng ta tạo ra các cấu hình để xác định một chính sách, cấu hình các quy tắc phù hợp và đăng ký các loại cùng với một đánh chặn:

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

Chúng ta cũng cần một bộ chuyển đổi loại để chuyển đổi chuỗi đại diện của các thuộc tính tùy chỉnh để loại thích hợp:

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

Khi chúng tôi có tất cả những gì thiết lập chúng ta có thể tạo ra một container và tải cấu hình:

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

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

Kết quả sẽ là:

Invoking Do 
Do! 
Done Invoke 
Do Again! 

cho thấy rằng phương pháp đầu tiên là chặn trong khi thứ hai thì không.

+0

Cảm ơn rất nhiều sự trợ giúp! –

+2

@Tuzo, cấu hình trông như thế nào trong mã C#? Bạn vẫn cần 'AssemblyQualifiedTypeNameConverter' nếu nó được thực hiện trong mã? –

Các vấn đề liên quan