2013-11-20 10 views
5

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

पर विचार करें:

मैं गतिशील रूप से उत्पन्न वर्गों का एक सेट है, एक ज्ञात आधार वर्ग से इनहेरिट (यह BaseClass फोन की सुविधा देता है)। इन गतिशील रूप से जेनरेट किए गए वर्गों ने संबंधित विशेषताओं के साथ Properties गतिशील रूप से उत्पन्न किया है।

गुण हालांकि गतिशील रूप से उत्पन्न नहीं, एक कस्टम वर्ग के भी हैं:

List<PropertyInfo> result = target.GetType() 
    .GetProperties() 
    .Where(
    p => 
     p.GetCustomAttributes(typeof(TypeAttribute), true) 
     //.Where(ca => ((TypeAttribute)ca).) 
     .Any() 
    ) 
    .ToList(); 

जहां:

[AttributeUsage(AttributeTargets.Property)] 
class TypeAttribute: Attribute 
{ 
    private Type _type; 
    public Type Type 
    { 
     get { return _type; } 
    } 

    public TypeAttribute(Type t) 
    { 
     _type = t; 
    } 
} 

तो मैं करने के लिए, निश्चित रूप से क्रम, इस सौंपा विशेषता के मान लाने चाहते हैं targetBaseClass का उप-वर्ग है। सूची result हालांकि खाली है, और यह मुझे परेशान करता है।

मैं विशेषता

PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, 
      PropertyAttributes.HasDefault, propertyType, null); 
ConstructorInfo classCtorInfo = typeof(TypeAttribute). 
      GetConstructor(new Type[] { typeof(Type) }); 
CustomAttributeBuilder myCABuilder = new CustomAttributeBuilder(
      classCtorInfo, new object[] { getType(dataType) }); 
propertyBuilder.SetCustomAttribute(myCABuilder); 

का उपयोग कर जहां dataType प्रकार विशेषता में स्टोर करने के लिए है और tb वर्ग के लिए TypeBuilder है जोड़ें।

यदि मैं संपत्ति पर getCustomAttributes() करता हूं, तो मुझे उम्मीद है कि मैं जिसकी तलाश कर रहा हूं उसे छोड़कर अपेक्षित विशेषताओं को प्राप्त करें। लेकिन अगर मैं getCustomAttributesData() करता हूं तो मैं उन सभी को प्राप्त करता हूं, लेकिन जिसकी मैं तलाश कर रहा हूं वह CustomAttributeData है और TypeAttribute पर जाति योग्य नहीं है (यदि मैं वीएस डीबगर में उदाहरण की जांच करता हूं तो मैं देख सकता हूं कि निहित जानकारी TypeAttribute के लिए है)। मुझे लगता है कि यह समस्या का एक लक्षण है, लेकिन मुझे कारण नहीं मिल रहा है - समाधान बहुत कम है।

क्या कोई मुझे बता सकता है कि result सूची खाली क्यों है?

+0

ओह, यह मजेदार है; इसमें मेरे लिए टेस्ट रिग स्थापित करने में कुछ मिनट लगेंगे ... मुझे उम्मीद है कि कोई ऐसा कुछ स्पष्ट करेगा जब मैं ऐसा करता हूं! –

उत्तर

1

मेरे लिए ठीक काम करता है; क्या आप सुनिश्चित हैं कि आपकी संपत्ति और गेटर या सेटर विधि पर्याप्त रूप से मौजूद है कि यह वास्तव में एक संपत्ति के रूप में दिखाती है?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Reflection.Emit; 
[AttributeUsage(AttributeTargets.Property)] 
public class TypeAttribute : Attribute 
{ 
    private Type _type; 
    public Type Type 
    { 
     get { return _type; } 
    } 

    public TypeAttribute(Type t) 
    { 
     _type = t; 
    } 
} 

public class BaseClass 
{ 

} 

static class Program 
{ 
    static void Main() 
    { 
     var aName = new AssemblyName("MyAssembly"); 
     var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
       aName, AssemblyBuilderAccess.RunAndSave); 
     var mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); 
     var tb = mb.DefineType("MyType", TypeAttributes.Public, typeof(BaseClass)); 

     var propertyName = "MyProperty"; 
     var propertyType = typeof(int); 
     var propertyBuilder = tb.DefineProperty(propertyName, 
      PropertyAttributes.HasDefault, propertyType, null); 
     var classCtorInfo = typeof(TypeAttribute). 
        GetConstructor(new Type[] { typeof(Type) }); 

     Type tArg = typeof(float); // for no real reason 
     var myCABuilder = new CustomAttributeBuilder(
      classCtorInfo, new object[] { tArg }); 
     propertyBuilder.SetCustomAttribute(myCABuilder); 

     var field = tb.DefineField("myField", propertyType, FieldAttributes.Private); 
     var getter = tb.DefineMethod("get_" + propertyName, 
      MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Public, 
      propertyType, Type.EmptyTypes); 
     propertyBuilder.SetGetMethod(getter); 
     var il = getter.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldfld, field); 
     il.Emit(OpCodes.Ret); 
     var setter = tb.DefineMethod("set_" + propertyName, 
      MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Public, 
      typeof(void), new[] { typeof(int) }); 
     il = setter.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Ldarg_1); 
     il.Emit(OpCodes.Stfld, field); 
     il.Emit(OpCodes.Ret); 
     propertyBuilder.SetSetMethod(setter); 
     var target = Activator.CreateInstance(tb.CreateType());   

     List<PropertyInfo> result = target.GetType() 
      .GetProperties() 
      .Where(
      p => 
       p.GetCustomAttributes(typeof(TypeAttribute), true) 
       //.Where(ca => ((TypeAttribute)ca).) 
       .Any() 
      ).ToList(); 
    } 
} 

इसके अलावा, यह अधिक Attribute.IsDefined उपयोग करने के लिए अगर आप सिर्फ परवाह है कि यह बाहर निकल जाता है कुशल है।

List<PropertyInfo> result = target.GetType().GetProperties() 
     .Where(p => Attribute.IsDefined(p, typeof(TypeAttribute), true)).ToList(); 

भी ध्यान दें कि मैं getType(dataType) सामान धोखा किया था - मैं नहीं देख सकता था कि क्या कर रहा था के रूप में यह प्रश्न में नहीं था। सुनिश्चित करें कि यह Type देता है।

+0

जैसा कि आपने कहा था। मैं इसे एक अलग समस्या में चलाने की कोशिश न करने के लिए थोड़ा बेवकूफ महसूस कर रहा हूं, लेकिन मैं अभी भी यहां रहूंगा, लेकिन एक अलग सवाल के साथ। लेकिन, जब मैं अपने "असली" एप्लिकेशन में उस कामकाजी कोड को कॉपी करता हूं तो यह काम नहीं करेगा। परिणाम शून्य लंबाई की एक सूची है। एक ही डब्ल्यूपीएफ आवेदन में कॉपी किया गया कोड। अपराधी होने के लिए डब्ल्यूपीएफ को बाहर करने के लिए मैंने काम किया और डब्ल्यूपीएफ आवेदन खाली कर दिया, जो काम करता था। तो यह मेरे "असली आवेदन" में कुछ है। समस्या यह पता लग रहा है कि क्या ... – fredrik

+0

ऐसी मूर्खतापूर्ण गलती। सार्वजनिक रूप से 'TypeAttribute' घोषित करने के लिए तत्काल भूलना इसका कारण होगा।इसे आपके कामकाजी कोड के बिना नहीं देखा था। धन्यवाद। – fredrik

+0

जब मैं 'परिणाम [0] करने की कोशिश करता हूं। .GetCustomAttributes()' मुझे स्वत: जेनरेटेड असेंबली पर 'FileNotFoundException' मिलता है। मुझे कोई विचार नहीं आया कि मुझे क्या करना है? (ओसीसी मैं जांचता हूं कि सूची में कम से कम एक परिणाम है) – fredrik

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