简体   繁体   English

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

[英]Open delegate to IFormattable.ToString method in struct (Int32, DateTime)

I want to create an open delegate to the method ToString(string, IFormatprovider) of a struct ( Int32 , DateTime , whatever): 我想为结构( Int32DateTime ,无论如何)的方法ToString(string, IFormatprovider)创建一个开放的委托:

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!

It keeps throwing the ArgumentException with message "Error binding to target method.". 它不断抛出ArgumentException,并显示消息“错误绑定到目标方法”。

I've read almost all stackoverflow articles on this subject, I have experimented with and without ref , I have added and removed the null when creating the delegate. 我已经阅读了有关该主题的几乎所有stackoverflow文章,我尝试使用ref和不使用ref ,在创建委托时添加和删除了null Nothing seems to help. 似乎没有任何帮助。

Has anyone any clue? 有任何线索吗?

* EDIT * *编辑*

When I create my own struct with the same method, the code above (with DateTime replaced my MyStruct) works perfectly fine. 当我用相同的方法创建自己的结构时,上面的代码(用DateTime替换了MyStruct)可以很好地工作。

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

What makes an Int32 or DateTime so different? 是什么使Int32DateTime如此与众不同?

* EDIT * *编辑*

As requested I added a complete "working" program. 根据要求,我添加了完整的“工作”程序。 What I forgot to mention: I am working on .NET framework 3.5. 我忘了提的是:我正在使用.NET Framework 3.5。 Furthermore, as I stated before, this is all working on MyStruct . 此外,正如我之前所说,这一切都在MyStruct Except, when I implement the interface IFormattable , it also does not work anymore. 除此之外,当我实现IFormattable接口IFormattable ,它也不再起作用。

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;
        }
    }
}

* EDIT * *编辑*

It all works perfectly on .NET Framework 4.x, but that is NOT a solution for me. 所有这些都可以在.NET Framework 4.x上完美运行,但这对我来说不是一个解决方案。

I don't know the answer for that specific problem but maybe you can build your own delegate: 我不知道该特定问题的答案,但是也许您可以构建自己的代表:

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();
}

Can be used like: 可以像这样使用:

var d = CreateConverter<MyStruct>();
Console.WriteLine(d(new MyStruct(), "", CultureInfo.CurrentCulture));

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

EDIT to make sure that the input is of the correct type 编辑以确保输入的类型正确

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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 IFormattable.ToString 对于十六进制格式没有按预期工作 - IFormattable.ToString not working as expected for Hexadecimal formatting Int32是DateTime吗? - Int32 Is DateTime? LINQ to Entities无法识别方法&#39;System.String ToString(Int32)&#39;方法 - LINQ to Entities does not recognize the method 'System.String ToString(Int32)' method LINQ to Entities无法识别方法&#39;System.String ToString(Int32)&#39; - LINQ to Entities does not recognize the method 'System.String ToString(Int32)' 将月份数字转换为字符串错误时:无法识别方法&#39;System.String ToString(Int32)&#39; - When converting month number to string error : Does not recognize the method 'System.String ToString(Int32)' 如何为所有IEnumerable覆盖ToString()方法 <Int32> ? - How can I override ToString() method for all IEnumerable<Int32>? 是否可以对内置类型的object.ToString()和IFormattable.ToString(string,IFormatProvider)之间的关系做出任何假设? - Can any assumptions be made about the relationship between object.ToString() and IFormattable.ToString(string, IFormatProvider) for built-in types? 自定义结构,以便将其序列化为Int32 - Customize a struct so that it serializes as a Int32 从“ DateTime”到“ Int32”的转换无效 - Invalid cast from 'DateTime' to 'Int32' LINQ to Entities无法识别方法&#39;Int32 GetMonth(System.DateTime)&#39;方法 - LINQ to Entities does not recognize the method 'Int32 GetMonth(System.DateTime)' method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM