2016-01-19 20 views
5

Yeni bir özel özellik türü oluşturmak ve daha sonra varolan bir türe eklemek için Mono.Cecil'i kullanıyorum.Üye başka bir modülde bildirilmiş ve içe aktarılması gerekiyor

Bunu göstermek için "SampleType" adlı türevi olan "Sample" adlı önceden var olan bir DLL'im var.

Mono.Cecil'i "NewAttribute" adlı "Örnek" içinde yeni bir türle örgülemek ve sonra bu özniteliği "SampleType" olarak eklemek istiyorum.

kod şöyle görünür: (tam olarak değil ama onun yeterince iyi örneğin)

static void AddCustomeAttribute() 
{ 
    var module = ModuleDefinition.ReadModule(AssemblyName); 
    var attrType = NewAttributeProvider.Add(module); 
    var ctor = attrType.GetConstructors().First(); 
    //module.Import(ctor); 
    CustomAttribute attribute = new CustomAttribute(ctor); 
    attribute.ConstructorArguments.Add(new CustomAttributeArgument(module.TypeSystem.String, "InternalClass")); 
    module.CustomAttributes.Add(attribute); 
    module.Write(AssemblyName); //error 
} 

-

public static TypeDefinition Add(ModuleDefinition targetModule) 
{ 
    var type = targetModule.AddType("Namespace", "NewAttribute", TypeAttributes.Public | TypeAttributes.Class, targetModule.Import(typeof(Attribute))); 
    var stringType = targetModule.TypeSystem.String; 
    var nameField = type.AddField(stringType, "_name"); 
    var nameProp = type.AddSimpleProperty(stringType, "Name", nameField); 

    // generate a constructor body 
    var constructor = type.AddConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, targetModule.TypeSystem.Void, new[] { stringType }); 
    constructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); 
    constructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); 
    constructor.Body.Instructions.Add(Instruction.Create(OpCodes.Stfld, nameField)); 
    constructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); 

    var attrUsageType = targetModule.Import(typeof(AttributeUsageAttribute)).Resolve(); 
    //var att = targetModule.Import(typeof(AttributeUsageAttribute)); 
    //targetModule.Import(attrUsageType); 
    var attributeTargetsType = targetModule.Import(typeof(AttributeTargets)); 
    //targetModule.Import(attributeTargetsType); 
    var propertiesToSet = new Dictionary<string, Tuple<TypeReference, object>> 
    { 
     {"AllowMultiple", Tuple.Create(targetModule.TypeSystem.Boolean, (object)true)} 
    }; 
    var usageAttr = type.AddCustomAttribute(attrUsageType, new[] { attributeTargetsType }, propertiesToSet); 
    //targetModule.Import(usageAttr.AttributeType); 
    targetModule.Types.Add(type); 
    return type; 
} 

-

public static CustomAttribute AddCustomAttribute(this TypeDefinition type, TypeDefinition attrType, TypeReference[] ctorParameters, Dictionary<string, Tuple<TypeReference, object>> propetiesToSet) 
{ 
    var attrUsageCtor = attrType.GetConstructors().Single(ctor => ctor.Parameters.Count == ctorParameters.Length && ValidateParameters(ctor.Parameters, ctorParameters)); 
    type.Module.Import(attrUsageCtor); 
    Collection<CustomAttributeNamedArgument> properties = new Collection<CustomAttributeNamedArgument>(); 
    foreach (KeyValuePair<string, Tuple<TypeReference, object>> typeReference in propetiesToSet) 
    { 
     properties.Add(new CustomAttributeNamedArgument(typeReference.Key, new CustomAttributeArgument(typeReference.Value.Item1, typeReference.Value.Item2))); 
    } 
    var customeAttr = new CustomAttribute(attrUsageCtor); 
    foreach (var property in properties) 
    { 
     customeAttr.Properties.Add(property); 
    } 
    type.CustomAttributes.Add(customeAttr); 
    return customeAttr; 
} 

Gördüğünüz gibi, yorumlardaki Bu kod, sorunu çözmek için başarıya ulaştığım girişimlerdir. ben bir şey eksik eminim ama ne olduğunu bilmiyorum .. şu imzaya sahip Cecil

cevap

10

İthalat yöntemleri:

TypeReference Import(TypeReference type) 
MethodReference Import(MethodReference method) 

İthalat bir türü veya bir yöntemi alır olursa olsun nerede tanımlanırlar ve mevcut modül için bir referans oluştururlar. Geri döndükleri şeyi kullanmazsanız, kodunuz doğru değildir.

Örneğin, yazın: Eğer mscorlib tanımlanan yapıcısı ile modülü için Bu durumda

var attrUsageCtor = attrType.GetConstructors().Single(ctor => ...); 
type.Module.Import(attrUsageCtor); 

, bir CustomAttribute yaratıyorsun. Modülünüzdeki yapıcı için bir referans oluşturmanız ve onu kullanmanız gerekir: İçe aktarma sonucu, özel özniteliği oluştururken kullanmanız gereken şeydir.

İçe Aktarım'ın tüm kullanımlarını gözden geçirmenizi ve

+0

numaralı ürünü doğrulamanızı öneririz. Bu benim de sorunumu çözdü. Aşağıdaki cümle önemli olan şeydir: "İçe aktarmanın sonucu, özel öznitelik oluşturulurken kullanmanız gereken şeydir". – m1o2

İlgili konular