Ninject Conventions and Interception(Ninject Conventions and Interception)
我想用拦截属性来装饰我的服务,然后让基于约定的绑定为我设置拦截器。 我不希望我的属性从拦截属性继承...如果我可以避免它。
例如,我有以下课程:
[Log] public class SomeClassToLog { public void DoSomething() { ... } }
我明白我可以绑定如下:
var kernel = new StandardKernel(); kernel.Bind(x => x.FromAssembliesMatching("SomeProject.*") .SelectAllClasses() .WithAttribute(typeof(LogAttribute)) .BindToSelf().Configure(syntax => syntax.Intercept().With(LogInterceptor)));
如何使用不同的属性和拦截器组合来做到这一点? 例如:
如果我有Log和Authorize属性,我将不得不配置3组绑定? (1表示没有授权的日志,1表示没有日志的授权,1表示日志和授权的日志)。
更新:虽然我找不到基于原始问题参数的解决方案,但我偶然发现了一个类似的问题,这个问题引导我找到最终解决的问题。 这是源代码:
注意: Common.Interception.Interceptors命名空间位于一个程序集中 ,该程序集引用了Ninject.Extensions.Interception(及其所有必需的依赖项)。 我的属性在一个单独的程序集中定义,没有自己的依赖项。
MiscExtensions.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Common.Interception.Interceptors { // TODO: Remove the dependence on these eventually /// <summary> /// A bundle of extension methods which I needed to borrow from ninject source since they were internal: /// Ninject.Extensions.Interception.Infrastructure.Language /// ExtensionsForIEnumerable /// ExtensionsForMethodInfo /// ExtensionsForICustomAttributeProvider /// </summary> internal static class MiscExtensions { /// <summary> /// Converts all of the items in the specified series using the specified converter. /// </summary> /// <typeparam name="TInput">The type of items contained in the input list.</typeparam> /// <typeparam name="TOutput">The type of items to return.</typeparam> /// <param name="items">The series of items to convert.</param> /// <param name="converter">The converter to use to convert the items.</param> /// <returns>A list of the converted items.</returns> public static IEnumerable<TOutput> Convert<TInput, TOutput>(this IEnumerable<TInput> items, Func<TInput, TOutput> converter) { return items.Select(converter); } /// <summary> /// Skips the last items where the count of skipped items is given by count. /// </summary> /// <typeparam name="T">The type of the enumerable.</typeparam> /// <param name="source">The source.</param> /// <param name="count">The count of skipped items.</param> /// <returns>An enumerable that skippes the last items from the source enumerable.</returns> public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count) { var enumerator = source.GetEnumerator(); var items = new Queue<T>(); while (enumerator.MoveNext()) { if (count-- <= 0) { yield return items.Dequeue(); } items.Enqueue(enumerator.Current); } } private const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; public static PropertyInfo GetPropertyFromMethod(this MethodInfo method, Type implementingType) { if (!method.IsSpecialName) { return null; } var isGetMethod = method.Name.Substring(0, 3) == "get"; var returnType = isGetMethod ? method.ReturnType : method.GetParameterTypes().Last(); var indexerTypes = isGetMethod ? method.GetParameterTypes() : method.GetParameterTypes().SkipLast(1); return implementingType.GetProperty(method.Name.Substring(4), DefaultBindingFlags, null, returnType, indexerTypes.ToArray(), null); } public static PropertyInfo GetPropertyFromMethod(this MethodInfo method) { if (!method.IsSpecialName) { return null; } return method.DeclaringType.GetProperty(method.Name.Substring(4), DefaultBindingFlags); } /// <summary> /// Gets the types of the parameters of the method. /// </summary> /// <param name="method">The method in question.</param> /// <returns>An array containing the types of the method's parameters.</returns> public static IEnumerable<Type> GetParameterTypes(this MethodBase method) { return method.GetParameters().Convert(p => p.ParameterType); } /// <summary> /// Gets the method handle of either the method or its generic type definition, if it is /// a generic method. /// </summary> /// <param name="method">The method in question.</param> /// <returns>The runtime method handle for the method or its generic type definition.</returns> public static RuntimeMethodHandle GetMethodHandle(this MethodBase method) { var mi = method as MethodInfo; if (mi != null && mi.IsGenericMethod) { return mi.GetGenericMethodDefinition().MethodHandle; } return method.MethodHandle; } /// <summary> /// Gets the first attribute of a specified type that decorates the member. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns>The first attribute matching the specified type.</returns> public static T GetOneAttribute<T>(this ICustomAttributeProvider member) where T : Attribute { var attributes = member.GetCustomAttributes(typeof(T), true) as T[]; return (attributes == null) || (attributes.Length == 0) ? null : attributes[0]; } /// <summary> /// Gets the first attribute of a specified type that decorates the member. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns>The first attribute matching the specified type.</returns> public static object GetOneAttribute(this ICustomAttributeProvider member, Type type) { object[] attributes = member.GetCustomAttributes(type, true); return (attributes == null) || (attributes.Length == 0) ? null : attributes[0]; } /// <summary> /// Gets an array of attributes matching the specified type that decorate the member. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns>An array of attributes matching the specified type.</returns> public static T[] GetAllAttributes<T>(this ICustomAttributeProvider member) where T : Attribute { return member.GetCustomAttributes(typeof(T), true) as T[]; } /// <summary> /// Gets an array of attributes matching the specified type that decorate the member. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns>An array of attributes matching the specified type.</returns> public static object[] GetAllAttributes(this ICustomAttributeProvider member, Type type) { return member.GetCustomAttributes(type, true); } /// <summary> /// Determines whether the member is decorated with one or more attributes of the specified type. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns><see langword="True"/> if the member is decorated with one or more attributes of the type, otherwise <see langword="false"/>.</returns> public static bool HasAttribute<T>(this ICustomAttributeProvider member) where T : Attribute { return member.IsDefined(typeof(T), true); } /// <summary> /// Determines whether the member is decorated with one or more attributes of the specified type. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns><see langword="True"/> if the member is decorated with one or more attributes of the type, otherwise <see langword="false"/>.</returns> public static bool HasAttribute(this ICustomAttributeProvider member, Type type) { return member.IsDefined(type, true); } /// <summary> /// Determines whether the member is decorated with an attribute that matches the one provided. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <param name="attributeToMatch">The attribute to match against.</param> /// <returns><see langword="True"/> if the member is decorated with a matching attribute, otherwise <see langword="false"/>.</returns> public static bool HasMatchingAttribute<T>(this ICustomAttributeProvider member, T attributeToMatch) where T : Attribute { T[] attributes = member.GetAllAttributes<T>(); if ((attributes == null) || (attributes.Length == 0)) { return false; } return attributes.Any(attribute => attribute.Match(attributeToMatch)); } } }
AlternateInterceptorRegistrationStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Ninject; using Ninject.Components; using Ninject.Extensions.Interception; using Ninject.Extensions.Interception.Advice; using Ninject.Extensions.Interception.Planning.Directives; using Ninject.Extensions.Interception.Registry; using Ninject.Planning; using Ninject.Planning.Strategies; namespace Common.Interception.Interceptors { /// <summary> /// This is a derivation of InterceptorRegistrationStrategy from Ninject.Extensions.Interception.Planning.Strategies, merged with /// http://stackoverflow.com/questions/6386461/ninject-intercept-any-method-with-certain-attribute /// </summary> public class AlternateInterceptorRegistrationStrategy<TAttribute, TInterceptor> : NinjectComponent, IPlanningStrategy where TAttribute : Attribute where TInterceptor : IInterceptor { protected const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; public AlternateInterceptorRegistrationStrategy(IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry, IKernel kernel) { AdviceFactory = adviceFactory; AdviceRegistry = adviceRegistry; Kernel = kernel; } public IKernel Kernel { get; set; } public IAdviceFactory AdviceFactory { get; set; } public IAdviceRegistry AdviceRegistry { get; set; } public virtual void Execute(IPlan plan) { IEnumerable<MethodInfo> candidates = GetCandidateMethods(plan.Type); RegisterClassInterceptors(plan.Type, plan, candidates); foreach (MethodInfo method in candidates) { PropertyInfo property = method.GetPropertyFromMethod(plan.Type); ICustomAttributeProvider provider = (ICustomAttributeProvider)property ?? method; TAttribute[] attributes = provider.GetAllAttributes<TAttribute>(); if (attributes.Length == 0) { continue; } RegisterMethodInterceptor(plan.Type, method); // Indicate that instances of the type should be proxied. if (!plan.Has<ProxyDirective>()) { plan.Add(new ProxyDirective()); } } } protected virtual void RegisterClassInterceptors(Type type, IPlan plan, IEnumerable<MethodInfo> candidates) { var attributes = type.GetAllAttributes<TAttribute>(); if (attributes.Length == 0) { return; } foreach (MethodInfo method in candidates) { PropertyInfo property = method.GetPropertyFromMethod(type); ICustomAttributeProvider provider = (ICustomAttributeProvider) property ?? method; var config = Kernel.Get<IInterceptorConfig>(); if (config.DoNotInterceptAttribute == null) { // A "do not intercept" attribute wasn't defined in the config, so go ahead and register RegisterMethodInterceptor(type, method); } else if (!provider.IsDefined(config.DoNotInterceptAttribute, true)) { // The method wasn't decorated with the "do not intercept" attribute, so go ahead and register RegisterMethodInterceptor(type, method); } } if (!plan.Has<ProxyDirective>()) { plan.Add(new ProxyDirective()); } } protected virtual void RegisterMethodInterceptor(Type type, MethodInfo method) { IAdvice advice = AdviceFactory.Create(method); advice.Callback = request => request.Context.Kernel.Get<TInterceptor>(); var config = Kernel.TryGet<IInterceptorConfig>(); if (config != null) { advice.Order = config.GetOrder<TInterceptor>(); } AdviceRegistry.Register(advice); } protected virtual IEnumerable<MethodInfo> GetCandidateMethods(Type type) { MethodInfo[] methods = type.GetMethods(DefaultBindingFlags); return methods.Where(ShouldIntercept); } protected virtual bool ShouldIntercept(MethodInfo methodInfo) { return methodInfo.DeclaringType != typeof(object) && !methodInfo.IsPrivate;// && //!methodInfo.IsFinal; } } }
IInterceptorConfig.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public interface IInterceptorConfig { IInterceptorConfig SpecifyOrder<TInterceptor>(int order) where TInterceptor : IInterceptor; IInterceptorConfig SpecifyDoNotInterceptAttribute<TAttribute>() where TAttribute : Attribute; int GetOrder<TInterceptor>() where TInterceptor : IInterceptor; Type DoNotInterceptAttribute { get; } } }
InterceptorConfig.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public class InterceptorConfig : IInterceptorConfig { private readonly Dictionary<Type, int> _orderDictionary = new Dictionary<Type, int>(); public IInterceptorConfig SpecifyOrder<TInterceptor>(int order) where TInterceptor : IInterceptor { _orderDictionary.Add(typeof(TInterceptor), order); return this; } public IInterceptorConfig SpecifyDoNotInterceptAttribute<TAttribute>() where TAttribute : Attribute { DoNotInterceptAttribute = typeof(TAttribute); return this; } public int GetOrder<TInterceptor>() where TInterceptor : IInterceptor { return _orderDictionary[typeof(TInterceptor)]; } public Type DoNotInterceptAttribute { get; private set; } } }
TraceInterceptor.cs - 只是一个示例拦截器
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public class TraceInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("Enter Method"); invocation.Proceed(); Console.WriteLine("Exit Method"); } } }
注意:这是一个简单的控制台应用程序,显示如何连接属性/拦截器。 这依赖于Ninject.Extensions.Interception.DynamicProxy和Ninject.Extensions.Conventions(及其所有必需的依赖项)
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Common.Interception.Attributes; using Common.Interception.Interceptors; using Ninject; using Ninject.Extensions.Conventions; using Ninject.Planning.Strategies; using SomeProject.Infrastructure; namespace SomeProject.ConsoleApp { class Program { static void Main(string[] args) { var kernel = new StandardKernel(); kernel.Components.Add<IPlanningStrategy, AlternateInterceptorRegistrationStrategy<TraceAttribute, TraceInterceptor>>(); kernel.Components.Add<IPlanningStrategy, AlternateInterceptorRegistrationStrategy<AuthorizeAttribute, AuthorizeInterceptor>>(); // I needed a way to specify execution order and "DoNotIntercept" without deriving from attributes that would force ninject references all over my domain // not 100% confident this is the best way - but it works kernel.Bind<IInterceptorConfig>().ToConstant(new InterceptorConfig() .SpecifyOrder<TraceInterceptor>(1) .SpecifyOrder<AuthorizeInterceptor>(0) .SpecifyDoNotInterceptAttribute<DoNotInterceptAttribute>()); // SomeProject.Infrastructure contains my service classes decorated with my custom attributes kernel.Bind(x => x.FromAssembliesMatching("SomeProject.Infrastructure") .SelectAllClasses() .BindToSelf()); var a = kernel.Get<SomeServiceA>(); var b = kernel.Get<SomeServiceB>(); Console.WriteLine("Calling a.DoSomeStuff()..."); a.DoSomeStuff(); Console.WriteLine("Calling b.DoMyThing()..."); b.DoMyThing(); Console.WriteLine("Calling b.NowTraceThis()..."); b.NowTraceThis(); Console.ReadLine(); } } }
I want to decorate my services with attributes for interception, and then have conventions based binding set the interceptors up for me. I don't want my attributes to inherit from the interception attributes... if I can avoid it.
For example, I have the following class:
[Log] public class SomeClassToLog { public void DoSomething() { ... } }
I understand I can bind this as follows:
var kernel = new StandardKernel(); kernel.Bind(x => x.FromAssembliesMatching("SomeProject.*") .SelectAllClasses() .WithAttribute(typeof(LogAttribute)) .BindToSelf().Configure(syntax => syntax.Intercept().With(LogInterceptor)));
How can I do this with different combinations of attributes and interceptors? For example:
If I have Log and Authorize attributes I would have to configure 3 sets of bindings? (1 for log without authorize, 1 for authorize without log and one for both log and authorize).
Updated: While I couldn't find a solution based on my original question parameters, I did stumble upon a similar question which lead me to the solution I ended up going with. Here is the source code:
Notes: Common.Interception.Interceptors namespace is in an assembly which has a reference to Ninject.Extensions.Interception (and all of its required dependencies). My attributes are defined in a separate assembly with no dependencies of their own.
MiscExtensions.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace Common.Interception.Interceptors { // TODO: Remove the dependence on these eventually /// <summary> /// A bundle of extension methods which I needed to borrow from ninject source since they were internal: /// Ninject.Extensions.Interception.Infrastructure.Language /// ExtensionsForIEnumerable /// ExtensionsForMethodInfo /// ExtensionsForICustomAttributeProvider /// </summary> internal static class MiscExtensions { /// <summary> /// Converts all of the items in the specified series using the specified converter. /// </summary> /// <typeparam name="TInput">The type of items contained in the input list.</typeparam> /// <typeparam name="TOutput">The type of items to return.</typeparam> /// <param name="items">The series of items to convert.</param> /// <param name="converter">The converter to use to convert the items.</param> /// <returns>A list of the converted items.</returns> public static IEnumerable<TOutput> Convert<TInput, TOutput>(this IEnumerable<TInput> items, Func<TInput, TOutput> converter) { return items.Select(converter); } /// <summary> /// Skips the last items where the count of skipped items is given by count. /// </summary> /// <typeparam name="T">The type of the enumerable.</typeparam> /// <param name="source">The source.</param> /// <param name="count">The count of skipped items.</param> /// <returns>An enumerable that skippes the last items from the source enumerable.</returns> public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count) { var enumerator = source.GetEnumerator(); var items = new Queue<T>(); while (enumerator.MoveNext()) { if (count-- <= 0) { yield return items.Dequeue(); } items.Enqueue(enumerator.Current); } } private const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; public static PropertyInfo GetPropertyFromMethod(this MethodInfo method, Type implementingType) { if (!method.IsSpecialName) { return null; } var isGetMethod = method.Name.Substring(0, 3) == "get"; var returnType = isGetMethod ? method.ReturnType : method.GetParameterTypes().Last(); var indexerTypes = isGetMethod ? method.GetParameterTypes() : method.GetParameterTypes().SkipLast(1); return implementingType.GetProperty(method.Name.Substring(4), DefaultBindingFlags, null, returnType, indexerTypes.ToArray(), null); } public static PropertyInfo GetPropertyFromMethod(this MethodInfo method) { if (!method.IsSpecialName) { return null; } return method.DeclaringType.GetProperty(method.Name.Substring(4), DefaultBindingFlags); } /// <summary> /// Gets the types of the parameters of the method. /// </summary> /// <param name="method">The method in question.</param> /// <returns>An array containing the types of the method's parameters.</returns> public static IEnumerable<Type> GetParameterTypes(this MethodBase method) { return method.GetParameters().Convert(p => p.ParameterType); } /// <summary> /// Gets the method handle of either the method or its generic type definition, if it is /// a generic method. /// </summary> /// <param name="method">The method in question.</param> /// <returns>The runtime method handle for the method or its generic type definition.</returns> public static RuntimeMethodHandle GetMethodHandle(this MethodBase method) { var mi = method as MethodInfo; if (mi != null && mi.IsGenericMethod) { return mi.GetGenericMethodDefinition().MethodHandle; } return method.MethodHandle; } /// <summary> /// Gets the first attribute of a specified type that decorates the member. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns>The first attribute matching the specified type.</returns> public static T GetOneAttribute<T>(this ICustomAttributeProvider member) where T : Attribute { var attributes = member.GetCustomAttributes(typeof(T), true) as T[]; return (attributes == null) || (attributes.Length == 0) ? null : attributes[0]; } /// <summary> /// Gets the first attribute of a specified type that decorates the member. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns>The first attribute matching the specified type.</returns> public static object GetOneAttribute(this ICustomAttributeProvider member, Type type) { object[] attributes = member.GetCustomAttributes(type, true); return (attributes == null) || (attributes.Length == 0) ? null : attributes[0]; } /// <summary> /// Gets an array of attributes matching the specified type that decorate the member. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns>An array of attributes matching the specified type.</returns> public static T[] GetAllAttributes<T>(this ICustomAttributeProvider member) where T : Attribute { return member.GetCustomAttributes(typeof(T), true) as T[]; } /// <summary> /// Gets an array of attributes matching the specified type that decorate the member. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns>An array of attributes matching the specified type.</returns> public static object[] GetAllAttributes(this ICustomAttributeProvider member, Type type) { return member.GetCustomAttributes(type, true); } /// <summary> /// Determines whether the member is decorated with one or more attributes of the specified type. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <returns><see langword="True"/> if the member is decorated with one or more attributes of the type, otherwise <see langword="false"/>.</returns> public static bool HasAttribute<T>(this ICustomAttributeProvider member) where T : Attribute { return member.IsDefined(typeof(T), true); } /// <summary> /// Determines whether the member is decorated with one or more attributes of the specified type. /// </summary> /// <param name="member">The member to examine.</param> /// <param name="type">The type of attribute to search for.</param> /// <returns><see langword="True"/> if the member is decorated with one or more attributes of the type, otherwise <see langword="false"/>.</returns> public static bool HasAttribute(this ICustomAttributeProvider member, Type type) { return member.IsDefined(type, true); } /// <summary> /// Determines whether the member is decorated with an attribute that matches the one provided. /// </summary> /// <typeparam name="T">The type of attribute to search for.</typeparam> /// <param name="member">The member to examine.</param> /// <param name="attributeToMatch">The attribute to match against.</param> /// <returns><see langword="True"/> if the member is decorated with a matching attribute, otherwise <see langword="false"/>.</returns> public static bool HasMatchingAttribute<T>(this ICustomAttributeProvider member, T attributeToMatch) where T : Attribute { T[] attributes = member.GetAllAttributes<T>(); if ((attributes == null) || (attributes.Length == 0)) { return false; } return attributes.Any(attribute => attribute.Match(attributeToMatch)); } } }
AlternateInterceptorRegistrationStrategy.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Ninject; using Ninject.Components; using Ninject.Extensions.Interception; using Ninject.Extensions.Interception.Advice; using Ninject.Extensions.Interception.Planning.Directives; using Ninject.Extensions.Interception.Registry; using Ninject.Planning; using Ninject.Planning.Strategies; namespace Common.Interception.Interceptors { /// <summary> /// This is a derivation of InterceptorRegistrationStrategy from Ninject.Extensions.Interception.Planning.Strategies, merged with /// http://stackoverflow.com/questions/6386461/ninject-intercept-any-method-with-certain-attribute /// </summary> public class AlternateInterceptorRegistrationStrategy<TAttribute, TInterceptor> : NinjectComponent, IPlanningStrategy where TAttribute : Attribute where TInterceptor : IInterceptor { protected const BindingFlags DefaultBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; public AlternateInterceptorRegistrationStrategy(IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry, IKernel kernel) { AdviceFactory = adviceFactory; AdviceRegistry = adviceRegistry; Kernel = kernel; } public IKernel Kernel { get; set; } public IAdviceFactory AdviceFactory { get; set; } public IAdviceRegistry AdviceRegistry { get; set; } public virtual void Execute(IPlan plan) { IEnumerable<MethodInfo> candidates = GetCandidateMethods(plan.Type); RegisterClassInterceptors(plan.Type, plan, candidates); foreach (MethodInfo method in candidates) { PropertyInfo property = method.GetPropertyFromMethod(plan.Type); ICustomAttributeProvider provider = (ICustomAttributeProvider)property ?? method; TAttribute[] attributes = provider.GetAllAttributes<TAttribute>(); if (attributes.Length == 0) { continue; } RegisterMethodInterceptor(plan.Type, method); // Indicate that instances of the type should be proxied. if (!plan.Has<ProxyDirective>()) { plan.Add(new ProxyDirective()); } } } protected virtual void RegisterClassInterceptors(Type type, IPlan plan, IEnumerable<MethodInfo> candidates) { var attributes = type.GetAllAttributes<TAttribute>(); if (attributes.Length == 0) { return; } foreach (MethodInfo method in candidates) { PropertyInfo property = method.GetPropertyFromMethod(type); ICustomAttributeProvider provider = (ICustomAttributeProvider) property ?? method; var config = Kernel.Get<IInterceptorConfig>(); if (config.DoNotInterceptAttribute == null) { // A "do not intercept" attribute wasn't defined in the config, so go ahead and register RegisterMethodInterceptor(type, method); } else if (!provider.IsDefined(config.DoNotInterceptAttribute, true)) { // The method wasn't decorated with the "do not intercept" attribute, so go ahead and register RegisterMethodInterceptor(type, method); } } if (!plan.Has<ProxyDirective>()) { plan.Add(new ProxyDirective()); } } protected virtual void RegisterMethodInterceptor(Type type, MethodInfo method) { IAdvice advice = AdviceFactory.Create(method); advice.Callback = request => request.Context.Kernel.Get<TInterceptor>(); var config = Kernel.TryGet<IInterceptorConfig>(); if (config != null) { advice.Order = config.GetOrder<TInterceptor>(); } AdviceRegistry.Register(advice); } protected virtual IEnumerable<MethodInfo> GetCandidateMethods(Type type) { MethodInfo[] methods = type.GetMethods(DefaultBindingFlags); return methods.Where(ShouldIntercept); } protected virtual bool ShouldIntercept(MethodInfo methodInfo) { return methodInfo.DeclaringType != typeof(object) && !methodInfo.IsPrivate;// && //!methodInfo.IsFinal; } } }
IInterceptorConfig.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public interface IInterceptorConfig { IInterceptorConfig SpecifyOrder<TInterceptor>(int order) where TInterceptor : IInterceptor; IInterceptorConfig SpecifyDoNotInterceptAttribute<TAttribute>() where TAttribute : Attribute; int GetOrder<TInterceptor>() where TInterceptor : IInterceptor; Type DoNotInterceptAttribute { get; } } }
InterceptorConfig.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public class InterceptorConfig : IInterceptorConfig { private readonly Dictionary<Type, int> _orderDictionary = new Dictionary<Type, int>(); public IInterceptorConfig SpecifyOrder<TInterceptor>(int order) where TInterceptor : IInterceptor { _orderDictionary.Add(typeof(TInterceptor), order); return this; } public IInterceptorConfig SpecifyDoNotInterceptAttribute<TAttribute>() where TAttribute : Attribute { DoNotInterceptAttribute = typeof(TAttribute); return this; } public int GetOrder<TInterceptor>() where TInterceptor : IInterceptor { return _orderDictionary[typeof(TInterceptor)]; } public Type DoNotInterceptAttribute { get; private set; } } }
TraceInterceptor.cs - just a sample interceptor
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Extensions.Interception; namespace Common.Interception.Interceptors { public class TraceInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("Enter Method"); invocation.Proceed(); Console.WriteLine("Exit Method"); } } }
Notes: Here is a simple console app that shows how to wire up the attributes/interceptors. This has dependencies on both Ninject.Extensions.Interception.DynamicProxy and Ninject.Extensions.Conventions (and all their required dependencies)
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Common.Interception.Attributes; using Common.Interception.Interceptors; using Ninject; using Ninject.Extensions.Conventions; using Ninject.Planning.Strategies; using SomeProject.Infrastructure; namespace SomeProject.ConsoleApp { class Program { static void Main(string[] args) { var kernel = new StandardKernel(); kernel.Components.Add<IPlanningStrategy, AlternateInterceptorRegistrationStrategy<TraceAttribute, TraceInterceptor>>(); kernel.Components.Add<IPlanningStrategy, AlternateInterceptorRegistrationStrategy<AuthorizeAttribute, AuthorizeInterceptor>>(); // I needed a way to specify execution order and "DoNotIntercept" without deriving from attributes that would force ninject references all over my domain // not 100% confident this is the best way - but it works kernel.Bind<IInterceptorConfig>().ToConstant(new InterceptorConfig() .SpecifyOrder<TraceInterceptor>(1) .SpecifyOrder<AuthorizeInterceptor>(0) .SpecifyDoNotInterceptAttribute<DoNotInterceptAttribute>()); // SomeProject.Infrastructure contains my service classes decorated with my custom attributes kernel.Bind(x => x.FromAssembliesMatching("SomeProject.Infrastructure") .SelectAllClasses() .BindToSelf()); var a = kernel.Get<SomeServiceA>(); var b = kernel.Get<SomeServiceB>(); Console.WriteLine("Calling a.DoSomeStuff()..."); a.DoSomeStuff(); Console.WriteLine("Calling b.DoMyThing()..."); b.DoMyThing(); Console.WriteLine("Calling b.NowTraceThis()..."); b.NowTraceThis(); Console.ReadLine(); } } }
原文:https://stackoverflow.com/questions/15098757
最满意答案
我不建议在这个环境中运行内置的rails服务器,因为它只适用于你的本地开发环境。
由于您使用的是Windows Azure,因此我建议您从Azure人员那里查看本教程。 它展示了如何设置nginx web服务器以及独角兽来托管Rails应用程序。
http://www.windowsazure.com/en-us/develop/ruby/tutorials/web-app-with-capistrano/
I would not recommend running the built-in rails server in this environment, as it is only meant for your local development environment.
Since you're on Windows Azure I would recommend you take a look at this tutorial from the Azure folks. It shows how to setup a nginx web server along with unicorn to host a Rails application.
http://www.windowsazure.com/en-us/develop/ruby/tutorials/web-app-with-capistrano/
相关问答
更多-
没有! Windows Azure Active Directory不是域控制器。 您不能将计算机加入Windows Azure AD。 您可以使用它将本地AD与Windows Azure AD同步,以轻松启用Web SSO(单一登录)。 您可以使用它来构建企业级Web应用程序。 您可以在这里阅读有关Windows Azure Active Directory的更多信息。 NO! Windows Azure Active Directory is NOT a Domain Controller. You c ...
-
如何在Azure Ubuntu VM中部署rails app + postgreSQL(How to deploy rails app + postgreSQL in Azure Ubuntu VM)[2021-09-29]
遗憾的是,Ruby on Rails不支持作为Azure Webapp平台,但你可以选择创建你的VM Heroku是一个PAAS平台,而Azure是PAAS和IAAS平台,但Azure PAAS还不支持ruby,Postgres也是尚未作为PAAS服务提供。 •我是否需要创建安装了Ubuntu Server的虚拟机并安装rails,ruby,git等? (已经完成)答案 - 这是正确的举措。 •我是否需要从服务器控制台手动从主存储库中提取最新代码,并在每次要更新服务器时重新启动服务器? 回答 - 使用任何持 ... -
您无法采取任何步骤来加速VM启动。 必须分配资源并配置VM。 我建议的是设置一个脚本,根据时间表自动启动/停止VM。 例如,如果您在教室环境中使用它们,您可以将它们设置为早期(早上6点?)并在每天下午5点之前关闭。 您可以在此处找到有关此内容的更多信息。 There are no steps you can take to speed up the VM start. Resources must be allocated and the VM provisioned. What I can recomme ...
-
这是运行Windows Server 2012的Azure VM的结果: PS D:\Users\***> query session SESSIONNAME USERNAME ID STATE TYPE DEVICE services 0 Disc console 1 Conn >rdp-tc ...
-
我不建议在这个环境中运行内置的rails服务器,因为它只适用于你的本地开发环境。 由于您使用的是Windows Azure,因此我建议您从Azure人员那里查看本教程。 它展示了如何设置nginx web服务器以及独角兽来托管Rails应用程序。 http://www.windowsazure.com/en-us/develop/ruby/tutorials/web-app-with-capistrano/ I would not recommend running the built-in rails s ...
-
在Windows Azure虚拟机上访问ruby应用程序[关闭](Accessing ruby application on Windows Azure Virtual Machine [closed])[2022-09-02]
好吧,我不能完全代表Azure,因为我还没有使用它,但应该有一种方法将端口80转发到你的VM。 您还应该确保IIS设置为侦听0.0.0.0:80而不是127.0.0.1:80 编辑:通常在云提供商的控制面板中设置端口转发,因此我首先要检查Azure为您配置VM的任何接口。 Well, I can't exactly speak for Azure as I haven't used it, but there should be a way to forward port 80 through to you ... -
什么是which pg_config的响应 如果它是这样的: / usr / bin /其中:no pg_config in ... 尝试使用以下命令重新安装: sudo apt-get install postgresql-devel As simple as it was, I just needed to install postgresql-server-dev-9.5 on my Azure Ubuntu VM. I just overlooked the error log :D
-
AFAIK虚拟机(IAAS)完全由您控制。 这些计算机上没有安装Azure代理,Azure不了解内部的操作。 任何与Azure相关的更新/升级/重新启动都发生在Azure计划的“外部”。 因此,您可以更改时区或其他设置。 AFAIK Virtual Machines (IAAS) are in your complete control. There are no Azure agents installed on those machines and Azure has no knowledge or c ...
-
Windows Azure虚拟机中的Ruby on rails应用程序(Ruby on rails application in Windows Azure Virtual Machine)[2021-10-09]
问题是你实际上没有“部署”任何东西。 您刚刚将rails应用程序复制到VM并运行rails s 。 生产轨道应用程序未以这种方式部署。 考虑使用带有unicorn的nginx或带乘客的apache / nginx。 The problem is you haven't actually "deployed" anything. You just copied your rails app to a VM and ran rails s. A production rails applications is ... -
使用rvm doc安装rvm和ruby。 这就足够了。 http://rvm.io/rvm/install use rvm doc to install rvm and ruby. It is sufficient. http://rvm.io/rvm/install