我实现了从字符串到对象的显式转换,称为Foo。
So => Foo f =(Foo)“foo data”;作品
我需要实现一个将字符串强制转换为泛型T的函数,在这种情况下,T是Foo数据类型。
public T Get<T>(object o){
// this always return false
if (typeof(T).IsAssignableFrom(typeof(String)))
{
// when i by pass the if above this throws invalid cast exception
return (T)(object)str;
}
return null;
}
// When I call this, it generated an error
// Invalid cast from 'System.String' to Foo
Foo myObj = Get<Foo>("another foo object");
// when I use the dynamic keyword it works but this is C# 4.0+ feature, my function is in the older framework
return (T)(dynamic)str;
答案 0 :(得分:2)
另请参阅@Jon Skeet的this answer - 特别是关于IsAssignableFrom
的引用。
我认为这不可能以你想象的方式实现。
我建议你在你的Foo课程上加上一个“接口合同” - 然后让泛型做他们的工作。
e.g。这样的事情 - 但这只是我输入的快速解决方案......
class Factory
{
public static T Create<T, TVal>(TVal obj) where T : class, IFoo<TVal>, new()
{
return new T { Value = obj }; // return default(T);
}
}
interface IFoo<TVal>
{
TVal Value { get; set; }
}
class Foo : IFoo<string>
{
public string Value { get; set; }
public Foo() { }
}
// ...
public T Get<T, TVal>(TVal obj) where T : class, IFoo<TVal>, new()
{
return Factory.Create<T, TVal>(obj);
}
你可以用类似的方式调用它 - 提供你have that luxury
- 知道类型等。
(但你可以解决这个问题并根据需要进行调整)
Foo foo = Get<Foo, string>("another text");
答案 1 :(得分:2)
使用Reflection的示例:
class Program
{
static void Main(string[] args)
{
Foo myObj = TypeResolver.Get<Foo>("Foo data");
}
}
class TypeResolver
{
public static T Get<T>(object obj)
{
if (typeof(T).CanExplicitlyCastFrom<string>())
{
return obj.CastTo<T>();
}
return default(T);
}
}
public static class Extensions
{
public static bool CanExplicitlyCastFrom<T>(this Type type)
{
if (type == null)
throw new ArgumentNullException("type");
var paramType = typeof(T);
var castOperator = type.GetMethod("op_Explicit",
new[] { paramType });
if (castOperator == null)
return false;
var parametres = castOperator.GetParameters();
var paramtype = parametres[0];
if (paramtype.ParameterType == typeof(T))
return true;
else
return false;
}
public static T CastTo<T>(this object obj)
{
var castOperator = typeof(T).GetMethod("op_Explicit",
new[] { typeof(string) });
if (castOperator == null)
throw new InvalidCastException("Can't cast to " + typeof(T).Name);
return (T)castOperator.Invoke(null, new[] { obj });
}
}
答案 2 :(得分:1)
如果你通过(object)
,那么它只是进行类型检查演员或框/ unbox(以IL术语:unbox-any) - 它不会使用运算符。将泛型和运算符一起使用的唯一方法是通过(dynamic)
而不是(object)
,但这在运行时会有一点工作。
答案 3 :(得分:0)
这是 reallllly 丑陋,但测试通过:
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest2
{
public T Get<T>(string str)
where T : CanCastFromString<T>, ICanInitFromString, new()
{
return (T)str;
}
[TestMethod]
public void Test()
{
var result = Get<Foo>("test");
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(Foo));
Assert.AreEqual("test", result.Value);
}
}
public class Foo : CanCastFromString<Foo>
{
public string Value { get; set; }
public override void InitFromString(string str)
{
Value = str;
}
}
public abstract class CanCastFromString<T> : ICanInitFromString
where T : CanCastFromString<T>, ICanInitFromString, new()
{
public static explicit operator CanCastFromString<T>(string str)
{
var x = new T();
x.InitFromString(str);
return x;
}
public abstract void InitFromString(string str);
}
public interface ICanInitFromString
{
void InitFromString(string str);
}
}
您可以通过在T
类string
上定义abstract
,然后约束您的{{1}来欺骗编译器,让他们知道您的通用CanCastFromString
可以从Get()
显式投射该抽象类的泛型函数。
答案 4 :(得分:0)
我假设你在课堂上定义了T,但无论如何我在方法上都有它。如果您可以在T上处理类约束,则此方法有效。
namespace TestCast {
class Program
{
public static T Get<T>(string o) where T : class
{
return o as T;
}
static void Main(string[] args)
{
Get<Breaker>("blah");
}
}
}
如果转换无效,则返回null,就像在Du的问题中一样,如果无法转换,则返回null。对于字符串,这将在有限的情况下工作。 as
运算符也不使用用户定义的转换运算符。