Create Dynamic type at runtime and set importingconstructor attribute

Mar 14, 2011 at 9:50 PM
Edited Mar 14, 2011 at 9:57 PM

I'm trying to create a class at runtime, with TypeBuilder. I need to decorate the constructor with ImportingConstructor attribute.

It's a generic derived class from a base class where the constructor needs an import.

 

 

 private static Type CreateType(string className, Type genericType)
        {
            // create a new type builder
            var typeBuilder = StaticModuleBuilder.DefineType(className, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass);
            typeBuilder.SetParent(typeof(AutoListViewModelBase<>).MakeGenericType(genericType));

            Type[] constructorArgs = { typeof(IAutoList) };
            var myConstructorBuilder = typeBuilder
                                    .DefineConstructor(MethodAttributes.Public |
                                    MethodAttributes.SpecialName |
                                    MethodAttributes.RTSpecialName |
                                    MethodAttributes.HideBySig,
                                    CallingConventions.Standard,
                                    constructorArgs);

            var ilGenerator = myConstructorBuilder.GetILGenerator();
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldarg_1);
            ilGenerator.Emit(OpCodes.Call, typeof(AutoListViewModelBase<>).MakeGenericType(genericType).GetConstructor(constructorArgs));
            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldarg_1);
            ilGenerator.Emit(OpCodes.Ret);

            // Generate our type

            Type[] exportParameters = { typeof(string), genericType.GetType() };
            var exportArgs = new object[] { className, typeof(IAutoListViewModel) };
            var exportCtorInfo = typeof(ExportAttribute).GetConstructor(BindingFlags.Instance | BindingFlags.Public, Type.DefaultBinder, exportParameters, null);
            var exportAttributeBuilder = new CustomAttributeBuilder(exportCtorInfo, exportArgs);
            typeBuilder.SetCustomAttribute(exportAttributeBuilder);


		/*problem is here*/
            var importingCtorInfo = typeof(ImportingConstructorAttribute).GetConstructor(Type.EmptyTypes);
            var importingCtorBuilder = new CustomAttributeBuilder(importingCtorInfo, Type.EmptyTypes);
            myConstructorBuilder.SetCustomAttribute(importingCtorBuilder);
            return typeBuilder.CreateType();
        } 

For some reason MEF throws an error when I instantiate the generated type.

Unable to cast object of type 'System.Object[]' to type 'System.ComponentModel.Composition.IAttributedImport[]'.

 

What Am I missing?

 

I'm expect a class like following code:

[Export("contract", typeof(IAutoListViewModel))]
    public class MyDerivedClass : AutoListViewModelBase<MyType>
    {
        [ImportingConstructor()]
        public MyDerivedClass (IAutoList autoList)
            : base(autoList)
        {
        }
}