/// <summary> /// Weave an aspect on methods matching with a specific pattern /// </summary> /// <typeparam name="T">Aspect</typeparam> /// <param name="pattern">Pattern</param> static public void Weave <T>(Func <MethodBase, bool> pattern, GenericWeavingFlags genericWeavingFlags) where T : class, IAspect, new() { var _weaver = new Weaver <T>(pattern, (genericWeavingFlags & NConcern.GenericWeavingFlags.EnableClosedGenericWeaving) != 0); lock (Aspect.m_Resource) { foreach (var _type in Aspect.Explore()) { if (!_type.IsDefined(typeof(HasNeptuneMethodsAttribute), false)) { continue; } if (_type.IsGenericTypeDefinition) { if ((genericWeavingFlags & NConcern.GenericWeavingFlags.EnableOpenGenericWeaving) == 0) { continue; } _weaver.Weave(_type, true); } else { _weaver.Weave(_type, false); } } if (_weaver.EnableConstructedGenericWeaving) { GenericWeavers.Add(_weaver); } } }
/// <summary> /// Release an aspect from all method. /// </summary> /// <typeparam name="T">Aspect</typeparam> static public void Release <T>() where T : class, IAspect, new() { lock (Aspect.m_Resource) { GenericWeavers.Remove <T>(); foreach (var _method in Aspect.Directory.Index <T>()) { Aspect.Directory.Remove(_method); } } }
public void Initialize() { lock (m_Handle) { if (!NeedInitialization) { return; } WeaverBase.GetNeptuneMethodIndex(this.Method, ref m_neptuneMethodIndex); if (Type.IsGenericTypeDefinition) { // do the remaining outside the lock NeedInitialization = false; goto FinalizeGenericTypeDefinition; } else { if (Method.IsGenericMethodDefinition) { if (Type.IsGenericType) { AddToDefinition(GenericWeavers.GetTypeDefinitionItem(Type.GetGenericTypeDefinition())); } } else { if (Method.IsGenericMethod) { AddToDefinition(GenericWeavers.GetTypeItem(Type)); } else { AddToDefinition(GenericWeavers.GetTypeDefinitionItem(Type.GetGenericTypeDefinition())); } } // do the remaining outside the lock } NeedInitialization = false; } // since we are outside the lock a competing thread may have done any of the following but none of it // should have problem with that, but they all may take lock on parent and we cannot allow that while child locked // due to risk od dead lock (we should always lock parent before child to avoid dead lock) if (this.GenericDefinition != null) { if (this.GenericDefinition.NeedInitialization) { this.GenericDefinition.Initialize(); } GenericDefinition.InstantiateChild(this); } if (Method.IsGenericMethodDefinition) { foreach (var _method in GenericWeavers.GetGenericMethodDefinitionItem(Method).ConstructedMethods) { // just need to create the entry it will add it self to this.GenericInstances Obtain(_method, m_neptuneMethodIndex); } } return; FinalizeGenericTypeDefinition: foreach (var _typeItem in GenericWeavers.GetTypeDefinitionItem(Type).ConstructedTypes.Values) { // todo Jens write a unittest that verify the claim below // we could do it now but then we might trigger type loading earlier than if not used // also the side effect unit tests assume it happens on first invoke if (_typeItem.InvokedMethods[m_neptuneMethodIndex]) { // just need to create the entry it will add it self to this.GenericInstances Obtain(_typeItem.Methods[m_neptuneMethodIndex]); } } return; }