2016-01-19 12 views
5

आयात करने की आवश्यकता है, मैं एक नया कस्टम विशेषता प्रकार बनाने के लिए Mono.Cecil का उपयोग करता हूं और फिर इसे किसी मौजूदा प्रकार में जोड़ता हूं।सदस्य को अन्य मॉड्यूल में घोषित किया गया है और इसे

इसे प्रदर्शित करने के लिए, मेरे पास "नमूना" नामक एक पूर्व-मौजूदा डीएलएल है जिसे "नमूना टाइप" कहा जाता है।

मैं मोनो। सेसिल को "न्यूप्लेट" नामक "नमूना" में एक नए प्रकार में बुनाई के लिए उपयोग करना चाहता हूं और फिर इस विशेषता को "नमूना टाइप" में जोड़ना चाहता हूं।

कोड इस तरह दिखता है: (वास्तव में नहीं है, लेकिन इसके काफी अच्छा उदाहरण के लिए)

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; 
} 

जैसा कि आप देख, टिप्पणी में कोड प्रयास है कि मैंने समस्या को ठीक करने के लिए किया लेकिन सफलता के बिना। मुझे यकीन है कि मैं कुछ याद कर रहा हूँ कर रहा हूँ लेकिन मैं क्या पता नहीं है ..

उत्तर

10

सेसिल में निम्नलिखित हस्ताक्षर आयात तरीके:

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

आयात एक प्रकार या एक विधि लेता है, कोई फर्क नहीं पड़ता जहां उन्हें परिभाषित किया गया है, और वर्तमान मॉड्यूल के लिए उनके लिए एक संदर्भ बनाते हैं। यदि आप जो भी लौटते हैं उसका उपयोग नहीं करते हैं, तो आपका कोड सही नहीं है।

उदाहरण के लिए, आप लिखते हैं:

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

उस मामले में, आप आप निर्माता mscorlib में परिभाषित के साथ मॉड्यूल के लिए एक CustomAttribute बना रहे हैं। आपको अपने मॉड्यूल में कन्स्ट्रक्टर के लिए एक संदर्भ बनाने की आवश्यकता है और इसका उपयोग करें: आयात का नतीजा यह है कि कस्टम विशेषता बनाने के दौरान आपको क्या उपयोग करना चाहिए।

मेरा सुझाव है कि आप आयात के सभी उपयोगों के माध्यम से जाएं और सत्यापित करें कि

+0

धन्यवाद! इसने मेरा मुद्दा भी हल कर लिया है। निम्नलिखित वाक्य महत्वपूर्ण है "आयात का परिणाम वह है जो आपको कस्टम विशेषता बनाते समय उपयोग करना चाहिए"। – m1o2

संबंधित मुद्दे