Urgent: CreateShared Attribute not working

Jun 9, 2009 at 1:53 AM

Hi There,

We had created our own custom attribute called CreateNewOnce that creates a singleton instance of an object per HTTPContext. We did this by inherting from KnownParameter and overriding the GetValue method. But this stopped working in the newer version of the Composite.Web.dll. We researched this and found that we have to create our own version of the parameterResolver and that there is a CreateShared attribute that has been developed by one of the developers on CodePlex that does exactly the same job. So we have tried to use this CreateShared attribute exactly as is on the codeplex site but its not working. It creates a new object in the same HTTPContext pipeline. Could someone please help and clarify what is going wrong? Is there any way I can look into the code the ILgenerater used in the EmitResolution method generates . Also, we put a breakpoint in the GetValue method and that method is never hit. We even put in debug.WriteLine statements in that method but it doesnt seem to be hitting it.  How can we debug whats going wrong...Help will be greatly appreciated. We are at our wits end here! Here in I have pasted code from the GetValue method and the EmitResolution method. Pl let me know if more info is required..

GetValue method:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<font size="2">

 

</font>

 

 

<font size="2">

System.Diagnostics.

</font>

Debug.WriteLine("Its in GetValue");<font size="2">

 

</font>

Guard.ArgumentNotNull(context, "context");<font size="2">

 

</font>

CompositionContainer container = (CompositionContainer)context.Locator.Get(new DependencyResolutionLocatorKey(typeof(CompositionContainer), null));<font size="2">

 

</font>

object instance = null;<font size="2">

 

</font>

IHttpContextLocatorService contextLocator = container.Locator.Get<IHttpContextLocatorService>(new DependencyResolutionLocatorKey(typeof(IHttpContextLocatorService), null));<font size="2">

 

</font>

IHttpContext httpContext = contextLocator.GetCurrentContext();<font size="2">

 

</font>

if (!httpContext.Items.Contains(_key))

{

<font size="2">

 

</font>

Type itemType = container.GetMappedType(_memberType);

instance = container.BuildNewItem(itemType);

httpContext.Items.Add(_key, instance);

}

<font size="2">

 

</font>

else

{

instance = httpContext.Items[_key];

}

<font size="2">

 

</font>

return instance;

 

Emit Resolution:

<font size="2">

 

</font>

public override void EmitParameterResolution(ILGenerator il, ParameterAttribute paramAttr, Type parameterType)

{

<font size="2">

System.Diagnostics.

</font>

Debugger.Log(0, "CreateNewOnce-EmitParameterResolution", (new System.Diagnostics.StackFrame()).GetMethod().Name);<font size="2">

 

</font>

MethodInfo getHeadOfChain = GetPropertyGetter<IBuilderContext>("HeadOfChain", typeof(IBuilderStrategy));<font size="2">

 

</font>

MethodInfo getLocator = GetPropertyGetter<IBuilderContext>("Locator", typeof(IReadWriteLocator));<font size="2">

 

</font>

MethodInfo getFromLocator = ObtainGetFromLocatorMethod();<font size="2">

 

</font>

MethodInfo buildUp = GetMethodInfo<IBuilderStrategy>("BuildUp",<font size="2">

 

</font>

typeof(IBuilderContext), typeof(Type), typeof(object),<font size="2">

 

</font>

typeof(string));<font size="2">

 

</font>

MethodInfo getHttpContext = GetMethodInfo<IHttpContextLocatorService>("GetCurrentContext");<font size="2">

 

</font>

MethodInfo contextItemsGetter = GetPropertyGetter<IHttpContext>("Items", typeof(System.Collections.IDictionary));<font size="2">

 

</font>

MethodInfo addToItems = GetMethodInfo<System.Collections.IDictionary>("Add", typeof(object), typeof(object));<font size="2">

 

</font>

MethodInfo itemsContains = GetMethodInfo<System.Collections.IDictionary>("Contains", typeof(object));<font size="2">

 

</font>

MethodInfo getItemInstace = GetMethodInfo<System.Collections.IDictionary>("get_Item", typeof(object));<font size="2">

 

</font>

ConstructorInfo keyCtor = GetConstructor<DependencyResolutionLocatorKey>(typeof(Type), typeof(string));<font size="2">

 

</font>

LocalBuilder httpContextLocator = il.DeclareLocal(typeof(IHttpContextLocatorService));<font size="2">

 

</font>

LocalBuilder httpContext = il.DeclareLocal(typeof(IHttpContext));<font size="2">

 

</font>

LocalBuilder itemsDictionary = il.DeclareLocal(typeof(System.Collections.IDictionary));<font size="2">

 

</font>

LocalBuilder objectInstance = il.DeclareLocal(parameterType);<font size="2">

 

</font>

CreateNewOnceAttribute createNewOnceAttribute = (CreateNewOnceAttribute)paramAttr;<font size="2">

 

</font>

string objKey = parameterType.ToString() + ";" + createNewOnceAttribute.Key ?? string.Empty;<font size="2">

 

</font>

// Get locator

<font size="2">

il.Emit(

</font>

OpCodes.Ldarg_0);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, getLocator, null);<font size="2">

 

</font>

// Create key

<font size="2">

EmitLoadType(il,

</font>

typeof(IHttpContextLocatorService));<font size="2">

il.Emit(

</font>

OpCodes.Ldnull);<font size="2">

il.Emit(

</font>

OpCodes.Newobj, keyCtor);<font size="2">

 

</font>

// Look up in locator

<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, getFromLocator, null);<font size="2">

il.Emit(

</font>

OpCodes.Stloc, httpContextLocator);<font size="2">

 

</font>

// Get the current http context from our context locator

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, httpContextLocator);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, getHttpContext, null);<font size="2">

il.Emit(

</font>

OpCodes.Stloc, httpContext);<font size="2">

 

</font>

// Get the items from the http context

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, httpContext);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, contextItemsGetter, null);<font size="2">

il.Emit(

</font>

OpCodes.Stloc, itemsDictionary);<font size="2">

 

</font>

Label noPreviousObjectLabel = il.DefineLabel();<font size="2">

 

</font>

Label doneLabel = il.DefineLabel();<font size="2">

 

</font>

// Do we have a context?

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, httpContext);<font size="2">

il.Emit(

</font>

OpCodes.Ldnull);<font size="2">

il.Emit(

</font>

OpCodes.Ceq);<font size="2">

 

</font>

// if context is null we create a new object

<font size="2">

il.Emit(

</font>

OpCodes.Brtrue, noPreviousObjectLabel);<font size="2">

 

</font>

// check if we have this key in our dictionary

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, itemsDictionary);<font size="2">

il.Emit(

</font>

OpCodes.Ldstr, objKey);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, itemsContains, null);<font size="2">

 

</font>

// check if the method returned false and branch to object creation

<font size="2">

il.Emit(

</font>

OpCodes.Brfalse, noPreviousObjectLabel);<font size="2">

 

</font>

// if we got this far we did find a previous object in the context, get it and jump to our exit code

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, itemsDictionary);<font size="2">

il.Emit(

</font>

OpCodes.Ldstr, objKey);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, getItemInstace, null);<font size="2">

il.Emit(

</font>

OpCodes.Stloc, objectInstance);<font size="2">

il.Emit(

</font>

OpCodes.Br, doneLabel);<font size="2">

 

</font>

// here we create an object and store it in our context

il.MarkLabel(noPreviousObjectLabel);

<font size="2">

 

</font>

// Get the head of the context chain

<font size="2">

il.Emit(

</font>

OpCodes.Ldarg_0); // Get context onto the stack

<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, getHeadOfChain, null); // Now head of chain is on the stack

<font size="2">

 

</font>

// Build up parameters to the BuildUp call - context, type, null existing, id

<font size="2">

il.Emit(

</font>

OpCodes.Ldarg_0); // Push context onto stack

EmitLoadType(il, parameterType);

<font size="2">

 

</font>

// Existing object is null

<font size="2">

il.Emit(

</font>

OpCodes.Ldnull);<font size="2">

 

</font>

// And the id

<font size="2">

il.Emit(

</font>

OpCodes.Ldarg_3);<font size="2">

 

</font>

// Call buildup on head of the chain

<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, buildUp, null);<font size="2">

il.Emit(

</font>

OpCodes.Stloc, objectInstance);<font size="2">

 

</font>

// add the created object into the context dictionary

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, itemsDictionary);<font size="2">

il.Emit(

</font>

OpCodes.Ldstr, objKey);<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, objectInstance);<font size="2">

il.EmitCall(

</font>

OpCodes.Callvirt, addToItems, null);<font size="2">

 

</font>

// push the created instance to the top of the stack (this will make it the return value!)

il.MarkLabel(doneLabel);

<font size="2">

il.Emit(

</font>

OpCodes.Ldloc, objectInstance);

 

}