在 struct (Int32, DateTime) 中打开对 IFormattable.ToString 方法的委托
Open delegate to IFormattable.ToString method in struct (Int32, DateTime)
我想为结构(Int32
、DateTime
等)的方法 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!
它不断抛出带有消息 "Error binding to target method." 的 ArgumentException。
我几乎阅读了所有关于这个主题的 Whosebug 文章,我尝试过使用和不使用 ref
,我在创建委托时添加和删除了 null
。似乎没有任何帮助。
有人知道吗?
* 编辑 *
当我使用相同的方法创建自己的结构时,上面的代码(用 DateTime 替换了我的 MyStruct)工作得很好。
public struct MyStruct
{
public string ToString(string format, IFormatProvider provider)
{
return null;
}
}
是什么让 Int32
或 DateTime
如此不同?
* 编辑 *
根据要求,我添加了一个完整的 "working" 程序。我忘了说:我正在研究 .NET Framework 3.5。此外,正如我之前所说,这一切都在 MyStruct
上进行。除了,当我实现接口 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;
}
}
}
* 编辑 *
它在 .NET Framework 上完美运行 4.x,但这不是我的解决方案。
我不知道该特定问题的答案,但也许您可以构建自己的委托:
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();
}
可以这样使用:
var d = CreateConverter<MyStruct>();
Console.WriteLine(d(new MyStruct(), "", CultureInfo.CurrentCulture));
d = CreateConverter<DateTime>();
Console.WriteLine(d(DateTime.Now, "yyyydd", CultureInfo.CurrentCulture));
编辑以确保输入的类型正确
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();
}
我想为结构(Int32
、DateTime
等)的方法 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!
它不断抛出带有消息 "Error binding to target method." 的 ArgumentException。
我几乎阅读了所有关于这个主题的 Whosebug 文章,我尝试过使用和不使用 ref
,我在创建委托时添加和删除了 null
。似乎没有任何帮助。
有人知道吗?
* 编辑 *
当我使用相同的方法创建自己的结构时,上面的代码(用 DateTime 替换了我的 MyStruct)工作得很好。
public struct MyStruct
{
public string ToString(string format, IFormatProvider provider)
{
return null;
}
}
是什么让 Int32
或 DateTime
如此不同?
* 编辑 *
根据要求,我添加了一个完整的 "working" 程序。我忘了说:我正在研究 .NET Framework 3.5。此外,正如我之前所说,这一切都在 MyStruct
上进行。除了,当我实现接口 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;
}
}
}
* 编辑 *
它在 .NET Framework 上完美运行 4.x,但这不是我的解决方案。
我不知道该特定问题的答案,但也许您可以构建自己的委托:
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();
}
可以这样使用:
var d = CreateConverter<MyStruct>();
Console.WriteLine(d(new MyStruct(), "", CultureInfo.CurrentCulture));
d = CreateConverter<DateTime>();
Console.WriteLine(d(DateTime.Now, "yyyydd", CultureInfo.CurrentCulture));
编辑以确保输入的类型正确
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();
}