क्या मैं सी # टाइप ऑब्जेक्ट को क्रमबद्ध कर सकता हूं?

मैं एक प्रकार ऑब्जेक्ट को निम्न तरीके से क्रमबद्ध करने की कोशिश कर रहा हूं:

Type myType = typeof (StringBuilder);
var serializer = new XmlSerializer(typeof(Type));
TextWriter writer = new StringWriter();
serializer.Serialize(writer, myType);

जब मैं ऐसा करता हूं, तो Serialize को कॉल निम्न अपवाद फेंकता है:

"टाइप सिस्टम .ext.StringBuilder की उम्मीद नहीं थी। का प्रयोग करें   XmlInclude या Soap विशेषताएँ निर्दिष्ट करने के लिए विशेषता शामिल करें जो नहीं हैं   स्थिर रूप से जाना जाता है। "

क्या टाइप ऑब्जेक्ट को क्रमबद्ध करने का कोई तरीका है? ध्यान दें कि मैं StringBuilder को क्रमबद्ध करने की कोशिश नहीं कर रहा हूं, लेकिन StringBuilder क्लास के बारे में मेटाडेटा वाला टाइप ऑब्जेक्ट है।

0
ro fr bn
प्रकार serialise क्यों? यदि deserialisation नहीं है। नेट यह इसका उपयोग नहीं कर सकता है, अगर यह है तो आप को पूरी तरह से योग्य नाम है।
जोड़ा लेखक Keith, स्रोत
यह सटीक कोड .net 6.1 में अपवाद उठाता है: xml दस्तावेज़ उत्पन्न करने में त्रुटि हुई थी। System.RuntimeType इसके सुरक्षा स्तर के कारण पहुंच योग्य नहीं है। केवल सार्वजनिक प्रकारों को संसाधित किया जा सकता है।
जोड़ा लेखक YMC, स्रोत

5 उत्तर

मुझे पता नहीं था कि एक टाइप ऑब्जेक्ट केवल एक स्ट्रिंग के साथ बनाया जा सकता है जिसमें पूरी तरह से योग्य नाम है। पूरी तरह से योग्य नाम प्राप्त करने के लिए, आप निम्न का उपयोग कर सकते हैं:

string typeName = typeof (StringBuilder).FullName;

इसके बाद आप इस स्ट्रिंग को तब भी जारी रख सकते हैं जब आवश्यक हो, फिर इस तरह के प्रकार का पुनर्निर्माण करें:

Type t = Type.GetType(typeName);

यदि आपको इस प्रकार का उदाहरण बनाना है, तो आप यह कर सकते हैं:

object o = Activator.CreateInstance(t);

यदि आप o.GetType() के मान की जांच करते हैं, तो यह स्ट्रिंगबिल्डर होगा, जैसा कि आप उम्मीद करेंगे।

0
जोड़ा
चेतावनी दीजिए कि टाइप। गेट टाइप (टाइपनाम); कॉल के समान ही असेंबली में केवल प्रकार के लिए काम करेगा।
जोड़ा लेखक GreyCloud, स्रोत
समाधान केवल पूर्ण नाम के बजाय Assembly QualifiedName का उपयोग करना है
जोड़ा लेखक GreyCloud, स्रोत
Type.GetType() जेनेरिक प्रकारों के लिए असफल हो जाएगा।
जोड़ा लेखक Beriz, स्रोत

सिस्टम के एमएसडीएन दस्तावेज के अनुसार। टाइप [1] आप सिस्टम को क्रमबद्ध करने में सक्षम होना चाहिए। टाइप ऑब्जेक्ट। हालांकि, चूंकि त्रुटि स्पष्ट रूप से System.Text.StringBuilder का जिक्र कर रही है, यह संभवतः कक्षा है जो धारावाहिक त्रुटि उत्पन्न कर रही है।

[1] Type Class (System) - http://msdn.microsoft.com/en-us/library/system.type.aspx

0
जोड़ा

बस इसकी परिभाषा को देखा, इसे Serializable के रूप में चिह्नित नहीं किया गया है। यदि आपको वास्तव में इस डेटा को क्रमबद्ध करने की आवश्यकता है, तो आपको इसे एक कस्टम क्लास में परिवर्तित करना पड़ सकता है जिसे इस तरह चिह्नित किया गया है।

public abstract class Type : System.Reflection.MemberInfo
    Member of System

Summary:
Represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types.

Attributes:
[System.Runtime.InteropServices.ClassInterfaceAttribute(0),
System.Runtime.InteropServices.ComDefaultInterfaceAttribute(System.Runtime.InteropServices._Type),
System.Runtime.InteropServices.ComVisibleAttribute(true)]
0
जोड़ा
अब यह Serializable विशेषता से सजाया गया है।
जोड़ा लेखक bjhuffine, स्रोत
सच नहीं है, System.Type serializable नहीं है लेकिन ठोस कार्यान्वयन System.RuntimeType है।
जोड़ा लेखक Felix K., स्रोत

Brian's answer works well if the type is in the same assembly as the call (like GreyCloud pointed out in one of the comments). So if the type is in another assembly you need to use the AssemblyQualifiedName as GreyCloud also pointed out.

हालांकि Assembly गुणवत्ता योग्य नाम </ए> संस्करण को सहेजता है, यदि आपके असेंबली के पास स्ट्रिंग में से एक से भिन्न संस्करण है, जहां आपके पास प्रकार है, तो यह काम नहीं करेगा।

मेरे मामले में यह एक मुद्दा था और मैंने इसे इस तरह हल किया:

string typeName = typeof (MyClass).FullName;

Type type = GetTypeFrom(typeName);

object myInstance = Activator.CreateInstance(type);

GetTypeFrom विधि

private Type GetTypeFrom(string valueType)
    {
        var type = Type.GetType(valueType);
        if (type != null)
            return type;

        try
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();                

            //To speed things up, we check first in the already loaded assemblies.
            foreach (var assembly in assemblies)
            {
                type = assembly.GetType(valueType);
                if (type != null)
                    break;
            }
            if (type != null)
                return type;

            var loadedAssemblies = assemblies.ToList();

            foreach (var loadedAssembly in assemblies)
            {
                foreach (AssemblyName referencedAssemblyName in loadedAssembly.GetReferencedAssemblies())
                {
                    var found = loadedAssemblies.All(x => x.GetName() != referencedAssemblyName);

                    if (!found)
                    {
                        try
                        {
                            var referencedAssembly = Assembly.Load(referencedAssemblyName);
                            type = referencedAssembly.GetType(valueType);
                            if (type != null)
                                break;
                            loadedAssemblies.Add(referencedAssembly);
                        }
                        catch
                        {
                            //We will ignore this, because the Type might still be in one of the other Assemblies.
                        }
                    }
                }
            }                
        }
        catch(Exception exception)
        {
            //throw my custom exception    
        }

        if (type == null)
        {
            //throw my custom exception.
        }

        return type;
    }

अगर किसी को इसकी ज़रूरत है तो मैं इसे पोस्ट कर रहा हूं।

0
जोड़ा

मुझे एक ही समस्या थी, और मेरा समाधान एक SerializableType वर्ग बनाना था। यह स्वतंत्र रूप से सिस्टम से बदलता है। टाइप करें, लेकिन यह एक स्ट्रिंग के रूप में serializes। आपको बस इतना करना है कि चर को एक SerializableType के रूप में घोषित करें, और तब से आप इसे सिस्टम के रूप में संदर्भित कर सकते हैं। टाइप करें।

यहां कक्षा है:

// a version of System.Type that can be serialized
[DataContract]
public class SerializableType
{
    public Type type;

   //when serializing, store as a string
    [DataMember]
    string TypeString
    {
        get
        {
            if (type == null)
                return null;
            return type.FullName;
        }
        set
        {
            if (value == null)
                type = null;
            else
            {
                type = Type.GetType(value);
            }
        }
    }

   //constructors
    public SerializableType()
    {
        type = null;
    }
    public SerializableType(Type t)
    {
        type = t;
    }

   //allow SerializableType to implicitly be converted to and from System.Type
    static public implicit operator Type(SerializableType stype)
    {
        return stype.type;
    }
    static public implicit operator SerializableType(Type t)
    {
        return new SerializableType(t);
    }

   //overload the == and != operators
    public static bool operator ==(SerializableType a, SerializableType b)
    {
       //If both are null, or both are same instance, return true.
        if (System.Object.ReferenceEquals(a, b))
        {
            return true;
        }

       //If one is null, but not both, return false.
        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }

       //Return true if the fields match:
        return a.type == b.type;
    }
    public static bool operator !=(SerializableType a, SerializableType b)
    {
        return !(a == b);
    }
   //we don't need to overload operators between SerializableType and System.Type because we already enabled them to implicitly convert

    public override int GetHashCode()
    {
        return type.GetHashCode();
    }

   //overload the .Equals method
    public override bool Equals(System.Object obj)
    {
       //If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

       //If parameter cannot be cast to SerializableType return false.
        SerializableType p = obj as SerializableType;
        if ((System.Object)p == null)
        {
            return false;
        }

       //Return true if the fields match:
        return (type == p.type);
    }
    public bool Equals(SerializableType p)
    {
       //If parameter is null return false:
        if ((object)p == null)
        {
            return false;
        }

       //Return true if the fields match:
        return (type == p.type);
    }
}

और उपयोग का एक उदाहरण:

[DataContract]
public class A
{

    ...

    [DataMember]
    private Dictionary _bees;

    ...

    public B GetB(Type type)
    {
        return _bees[type];
    }

    ...

}

आप Type.FullName के बजाय Assembly QualifiedName का उपयोग करने पर भी विचार कर सकते हैं - @GreyCloud द्वारा टिप्पणी देखें

0
जोड़ा
ओपी के प्रश्न शब्द के अनुसार +1 जवाब होना चाहिए
जोड़ा लेखक Askolein, स्रोत
+1 इसके अलावा, यह toString() को ओवरराइड करने के लायक हो सकता है साथ ही इसे वापस कर सकता है। टाइप करें? .ToString (); , जैसे कि इस वर्ग को कहीं भी निर्बाध रूप से उपयोग किया जा सकता है आप नियमित प्रकार की कक्षा का उपयोग करेंगे।
जोड़ा लेखक Zachary Canann, स्रोत