首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在struct中打开对IFormattable.ToString方法的委托(Int32,DateTime)

在struct中打开对IFormattable.ToString方法的委托(Int32,DateTime)
EN

Stack Overflow用户
提问于 2017-04-18 08:35:13
回答 1查看 158关注 0票数 0

我想要为结构的方法ToString(string, IFormatprovider) (Int32DateTime,随便什么)创建一个开放的委托:

代码语言:javascript
复制
public delegate string MyCoverter(ref DateTime from, string format, IFormatProvider provider);
...
var method = typeof(DateTime).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider)}); // Works!
var d= Delegate.CreateDelegate(typeof(MyCoverter), null, method); // Exception!

它一直使用“错误绑定到目标方法”的消息抛出ArgumentException。

我读过关于这个主题的几乎所有堆叠溢出的文章,我尝试过和不使用ref,我在创建委托时添加和删除了null。似乎什么也帮不上忙。

有什么线索吗?

*编辑*

当我用相同的方法创建自己的结构时,上面的代码(用DateTime替换了MyStruct)非常好。

代码语言:javascript
复制
public struct MyStruct
{
    public string ToString(string format, IFormatProvider provider)
    {
        return null;
    }
}

是什么使Int32DateTime如此不同?

*编辑*

应要求,我增加了一个完整的“工作”程序。我忘记提到的是:我正在开发.NET框架3.5。此外,正如我前面所说的,这些都是关于MyStruct的工作。但是,当我实现接口IFormattable时,它也不再工作了。

代码语言:javascript
复制
using System;

namespace OpenDelegates
{
    public delegate string MyCoverter<T>(ref T from, string format, IFormatProvider provider)
        where T : struct;

    class Program
    {
        static void Main(string[] args)
        {
            var method = typeof(MyStruct).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
            var d = Delegate.CreateDelegate(typeof(MyCoverter<MyStruct>), null, method);

            method = typeof(DateTime).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
            d = Delegate.CreateDelegate(typeof(MyCoverter<DateTime>), null, method);
        }
    }

    public struct MyStruct //: IFormattable
    {
        public string ToString(string format, IFormatProvider provider)
        {
            return null;
        }
    }
}

*编辑*

所有这些都在.NET Framework4.x上很好地工作,但对我来说不是一个解决方案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-18 09:30:03

我不知道这个具体问题的答案,但也许你可以建立自己的代表:

代码语言:javascript
复制
public static Func<object, string, IFormatProvider, string> CreateConverter<T>()
    where T : struct // not really needed
{
    var method = typeof(T).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
    if (method == null)
    {
        throw new InvalidOperationException(string.Format("The type {0} does not contain a suitable ToString-method.", typeof(T).FullName));
    }

    var instanceParameter = Expression.Parameter(typeof(object), "instance");
    var formatParameter = Expression.Parameter(typeof(string), "format");
    var providerParameter = Expression.Parameter(typeof(IFormatProvider), "provider");

    var convertedInstance = Expression.Convert(instanceParameter, typeof(T));
    var methodCall = Expression.Call(convertedInstance, method, formatParameter, providerParameter);
    var lambda = Expression.Lambda<Func<object, string, IFormatProvider, string>>(methodCall, instanceParameter, formatParameter, providerParameter);
    return lambda.Compile();
}

可用于:

代码语言:javascript
复制
var d = CreateConverter<MyStruct>();
Console.WriteLine(d(new MyStruct(), "", CultureInfo.CurrentCulture));

d = CreateConverter<DateTime>();
Console.WriteLine(d(DateTime.Now, "yyyydd", CultureInfo.CurrentCulture));

编辑以确保输入的类型是正确的

代码语言:javascript
复制
public static Func<T, string, IFormatProvider, string> CreateConverter<T>()
{
    var method = typeof(T).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string), typeof(IFormatProvider) }, null);
    if (method == null)
    {
        throw new InvalidOperationException(string.Format("The type {0} does not contain a suitable ToString-method.", typeof(T).FullName));
    }

    var instanceParameter = Expression.Parameter(typeof(T), "instance");
    var formatParameter = Expression.Parameter(typeof(string), "format");
    var providerParameter = Expression.Parameter(typeof(IFormatProvider), "provider");

    var methodCall = Expression.Call(instanceParameter, method, formatParameter, providerParameter);
    var lambda = Expression.Lambda<Func<T, string, IFormatProvider, string>>(methodCall, instanceParameter, formatParameter, providerParameter);
    return lambda.Compile();
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43467390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档