且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么不工作这个类型转换器?

更新时间:2022-10-17 16:27:40

我有这个问题,以及和解决方法的问题是,手动订阅到当前应用程序域的AssemblyResolve事件,并解决了组装​​。



这是远离很好的解决方案,但它似乎工作。我不知道为什么该框架的行为这种方式。我自己真的想找到解决这个问题的一个不太hackish的方式。

 公共无效DoMagic()
{
//注意:在此之后,您可以使用您的TypeConverter。
AppDomain.CurrentDomain.AssemblyResolve + =新ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

私人大会CurrentDomain_AssemblyResolve(对象发件人,ResolveEventArgs参数)
{
AppDomain中域=(应用程序域)发送;
的foreach(在domain.GetAssemblies大会ASM())
{
如果(asm.FullName == args.Name)
{
返回ASM;
}
}
返回NULL;
}


I am trying to understand why the below code is not working as expected; the TypeDescriptor is simply not picking up the custom converter from the attributes. I can only assume I have made an obvious mistake but I cannot see it.

-- edit -- this code seems to work when I run it in a console on its own, I'm actually calling a converter from within a much more complex application and from a different namespace.

-- edit -- alternatively any suggestions on how I can debug the TypeDescriptor so I can see what is going on and then I can probably answer this myself.

-- edit -- this problem is almost certainly related to pieces being in different assemblies.

-- edit -- It looks like this is not working because of some quirk of loading assemblies dynamically - this code is running under a plugin like architecture.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.ComponentModel;

namespace MyTest
{

    public class TestTester
    {
        public static void Main(string[] args)
        {
            object v = TypeDescriptor.GetConverter(typeof(MyTest.Test)).ConvertFromInvariantString("Test");
        }
    }

    public class TestConverter : TypeConverter
    {

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return false;
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
        {
            if (sourceType == typeof(string) || base.CanConvertFrom(context, sourceType))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(Test) || base.CanConvertTo(destinationType))
            {
                return true;
            }
            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value.GetType() == typeof(string))
            {
                Test t = new Test();
                t.TestMember = value as string;
                return t;
            }
            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string) && value.GetType() == typeof(Test))
            {
                return ((Test)value).TestMember;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

    }

    [TypeConverterAttribute(typeof(TestConverter))]
    public struct Test
    {
        public string TestMember { get; set; }
    }
}

I had this problem as well and a workaround to the problem is to subscribe to the AssemblyResolve event of the current application domain and resolve the assembly manually.

This is far from a good solution, but it seems to work. I have no idea why the framework behaves this way. I would myself really want to find a less hackish way of resolving this problem.

public void DoMagic()
{
    // NOTE: After this, you can use your typeconverter.
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    AppDomain domain = (AppDomain)sender;
    foreach (Assembly asm in domain.GetAssemblies())
    {
        if (asm.FullName == args.Name)
        {
            return asm;
        }
    }
    return null;
}