c# - एक वेब उपयोगकर्ता नियंत्रण के लिए एक पैरामीटर के रूप में int सूची उत्तीर्ण




asp.net typeconverter (6)

आप इसे एक स्ट्रिंग में पारित कर सकते हैं और एक निजी चर को पॉप्युलेट करने के लिए कॉमा पर विभाजित कर सकते हैं। एट्रिब्यूशन की अच्छी नहीं है, लेकिन काम करेगा।

private List<int> modules;
public string ModuleIds
{
  set{
    if (!string.IsNullOrEmpty(value))
    {
    if (modules == null) modules = new List<int>();
    var ids = value.Split(new []{','});
    if (ids.Length>0)
      foreach (var id in ids)
        modules.Add((int.Parse(id)));
    }
}

मैं इस तरह वेब उपयोगकर्ता नियंत्रण के लिए एक घोषणात्मक संपत्ति के रूप में एक int सूची (सूची) पास करना चाहता हूं:

<UC:MyControl runat="server" ModuleIds="1,2,3" />

मैंने ऐसा करने के लिए एक TypeConverter बनाया है:

public class IntListConverter : System.ComponentModel.TypeConverter
{
    public override bool CanConvertFrom(
           System.ComponentModel.ITypeDescriptorContext context, 
           Type sourceType)
    {
        if (sourceType == typeof(string)) return true;
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(
      System.ComponentModel.ITypeDescriptorContext context, 
      System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            string[] v = ((string)value).Split(
                new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            List<int> list = new List<int>();
            foreach (string s in vals)
            {
                list.Add(Convert.ToInt32(s));
            }
            return list
        }
        return base.ConvertFrom(context, culture, value);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context,
      Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor)) return true;
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context,
      System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(InstanceDescriptor) && value is List<int>)
        {
            List<int> list = (List<int>)value;
            ConstructorInfo construcor = typeof(List<int>).GetConstructor(new Type[] { typeof(IEnumerable<int>) });
            InstanceDescriptor id = new InstanceDescriptor(construcor, new object[] { list.ToArray() });
            return id;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

और फिर मेरी संपत्ति में विशेषता जोड़ा:

[TypeConverter(typeof(IntListConverter))]
public List<int> ModuleIds
{
    get { ... }; set { ... };
}

लेकिन मुझे रनटाइम पर यह त्रुटि मिलती है:

Unable to generate code for a value of type 'System.Collections.Generic.List'1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. This error occurred while trying to generate the property value for ModuleIds.

मेरा प्रश्न यहां पाया गया जैसा है , लेकिन समाधान मेरी समस्या का समाधान नहीं करता है:

अद्यतन: मुझे एक ऐसा पृष्ठ मिला जिसने पहली समस्या हल की। मैंने अपने सुधारों को दिखाने के लिए ऊपर दिए गए कोड को अपडेट किया है जोड़ा कोड CanConvertTo और ConvertTo विधियों है अब मुझे एक अलग त्रुटि मिलती है:

Object reference not set to an instance of an object.

यह त्रुटि अप्रत्यक्ष रूप से ConvertTo विधि में कुछ के कारण हो सकती है


जिस तरह से मैं सामान्य रूप से ऐसा करता हूं, संपत्ति को व्यूस्टेट संग्रह लपेटते हैं। काम करने के लिए अपना रास्ता बेहतर लगता है, लेकिन यह काम पूरा हो जाएगा:

public IList<int> ModuleIds
{
   get
   {
       string moduleIds = Convert.ToString(ViewState["ModuleIds"])

       IList<int> list = new Collection<int>();

       foreach(string moduleId in moduleIds.split(","))
       {
          list.Add(Convert.ToInt32(moduleId));
       }

      return list;
   }
}

मुझे लगता है कि आप सबसे अच्छा विकल्प हैं कि आपके उपयोगकर्ता के पास डेटाशोर्स-शैली संपत्ति है।

आप एक वस्तु के रूप में संपत्ति लेते हैं और फिर यह सुनिश्चित करने के लिए कि यह सही है, IList / IEnumerable / etc के खिलाफ कुछ प्रकार की जाँच करें।


मेरा मानना ​​है कि समस्या सेट {} है प्रकार कनवर्टर List<int> वापस एक स्ट्रिंग में बदलना चाहते हैं, लेकिन List<int> लिए CanConvertFrom() विफल रहता है।


कैसिनी में डिबगर को हुक करने के बाद, मुझे लगता है कि रिक्त रेफरी वास्तव में सिस्टम से आ रही है। Web.Compilation.CodeDomUtility.GenerateExpressionForValue, जो मूल रूप से int [] सरणी के लिए अभिव्यक्ति प्राप्त करने की कोशिश कर रहा है, आप सूची निर्माता में प्रवेश करते हैं। चूंकि इंट [] सरणी के लिए कोई प्रकार का विवरणक नहीं है, इसलिए यह विफल हो जाता है (और "गुण सेट अपवाद उत्पन्न नहीं कर सकता" के बजाय यह चाहिए कि प्रक्रिया में एक रिक्त रेफरी फेंकता है)।

मैं किसी सूची <int> में एक serializable मूल्य प्राप्त करने के तरीके के रूप में निर्मित नहीं कर सकता, इसलिए मैंने एक स्थिर विधि का उपयोग किया है:

class IntListConverter : TypeConverter {
    public static List<int> FromString(string value) {
       return new List<int>(
          value
           .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
           .Select(s => Convert.ToInt32(s))
       );
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
        if (destinationType == typeof(InstanceDescriptor)) {
            List<int> list = (List<int>)value;
            return new InstanceDescriptor(this.GetType().GetMethod("FromString"),
                new object[] { string.Join(",", list.Select(i => i.ToString()).ToArray()) }
            );
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

मैंने 2 गुणों को बनाकर कुछ समानता हल किया:

public List<int> ModuleIDs { get .... set ... }
public string ModuleIDstring { get ... set ... }

ModuleIDstring इसके मान को एक सूची में परिवर्तित करता है और ModuleIDs गुण सेट करता है।

यह एक प्रॉपर्टीग्रिड इत्यादि से मॉड्यूलआईडी उपयोग करने योग्य होगा।

ठीक है, सबसे अच्छा, टाइपराइफ समाधान नहीं, लेकिन मेरे लिए यह काम करता है







typeconverter