C# 使用反射动态地将属性转换为其实际类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/907882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cast a property to its actual type dynamically using reflection
提问by Keith K
I need to cast a property to its actual type dynamically. How do I/Can I do this using reflection?
我需要动态地将属性转换为其实际类型。我/我如何使用反射来做到这一点?
To explain the real scenario that I am working on a bit. I am trying to call the "First" extension method on an Entity Framework property. The specific property to be called on the Framework context object is passed as a string to the method (as well as the id of the record to be retrieved). So I need the actual type of the object in order to call the First method.
解释一下我正在处理的真实场景。我正在尝试在实体框架属性上调用“第一个”扩展方法。要在框架上下文对象上调用的特定属性作为字符串传递给方法(以及要检索的记录的 id)。所以我需要对象的实际类型才能调用 First 方法。
I can't use the "Where" method on the object as the lambda or delegate method still needs the actual type of the object in order to access the properties.
我不能在对象上使用“Where”方法,因为 lambda 或委托方法仍然需要对象的实际类型才能访问属性。
Also as the object is generated by the Entity Framework I can't cast the type to an interface and operate on that.
此外,由于对象是由实体框架生成的,因此我无法将类型转换为接口并对其进行操作。
This is scenario code:
这是场景代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
namespace NmSpc
{
public class ClassA
{
public int IntProperty { get; set; }
}
public class ClassB
{
public ClassA MyProperty { get; set; }
}
public class ClassC
{
static void Main(string[] args)
{
ClassB tester = new ClassB();
PropertyInfo propInfo = typeof(ClassB).GetProperty("MyProperty");
//get a type unsafe reference to ClassB`s property
Object property = propInfo.GetValue(tester, null);
//get the type safe reference to the property
ClassA typeSafeProperty = property as ClassA;
//I need to cast the property to its actual type dynamically. How do I/Can I do this using reflection?
//I will not know that "property" is of ClassA apart from at runtime
}
}
}
采纳答案by Keith K
I had some time so I tried to solve my problem using VS2010 and I think I was right previously when I though that the dynamic keywork would 'solve' my question. See the code below.
我有一些时间,所以我尝试使用 VS2010 解决我的问题,我认为我以前是对的,当时我认为动态键盘可以“解决”我的问题。请参阅下面的代码。
using System.Reflection;
namespace TempTest
{
public class ClassA
{
public int IntProperty { get; set; }
}
public class ClassB
{
public ClassB()
{
MyProperty = new ClassA { IntProperty = 4 };
}
public ClassA MyProperty { get; set; }
}
public class Program
{
static void Main(string[] args)
{
ClassB tester = new ClassB();
PropertyInfo propInfo = typeof(ClassB).GetProperty("MyProperty");
//get a type unsafe reference to ClassB`s property
dynamic property = propInfo.GetValue(tester, null);
//casted the property to its actual type dynamically
int result = property.IntProperty;
}
}
}
回答by Reed Copsey
Having a variable of a specific type is really only useful at compile time, and will not help you at runtime in using it in this way. Try to write the code where you would utilize this... you'll find that it keeps pushing the requirement to know the type to compile time at some level (maybe further up the call chain, but you'll still eventually need to type the concrete type for this to be useful).
拥有特定类型的变量实际上只在编译时有用,而不会帮助您在运行时以这种方式使用它。尝试编写您将使用它的代码......您会发现它不断推动知道类型的需求在某个级别编译时(可能在调用链的更上游,但您最终仍然需要输入对此有用的具体类型)。
One thing to keep in mind, though - if your type is a reference type, the object is still truly the type you've created. It's not like there is a benefit to having the object saved as your type vs. object. This is the beauty of reflection (as well as part of why it works). There really is no reason to try to "change" it's type at runtime in a cast, since it's still going to be an object.
但是要记住一件事 - 如果您的类型是引用类型,则对象仍然是您创建的真正类型。将对象另存为您的类型与对象并没有什么好处。这就是反射的美妙之处(也是它起作用的部分原因)。真的没有理由尝试在运行时在强制转换中“改变”它的类型,因为它仍然是一个对象。
回答by Nisus
public object CastPropertyValue(PropertyInfo property, string value) {
if (property == null || String.IsNullOrEmpty(value))
return null;
if (property.PropertyType.IsEnum)
{
Type enumType = property.PropertyType;
if (Enum.IsDefined(enumType, value))
return Enum.Parse(enumType, value);
}
if (property.PropertyType == typeof(bool))
return value == "1" || value == "true" || value == "on" || value == "checked";
else if (property.PropertyType == typeof(Uri))
return new Uri(Convert.ToString(value));
else
return Convert.ChangeType(value, property.PropertyType); }
回答by Keith K
Though I should post the solution to the real world problem.
虽然我应该发布现实世界问题的解决方案。
string objectType = "MyProperty";
using (MyEntitiesContext entitiesContext = new MyEntitiesContext())
{
try
{
string queryString = @"SELECT VALUE " + objectType+ " FROM MyEntitiesContext." + objectType + " AS " + objectType + " WHERE " + objectType + ".id = @id";
IQueryable<Object> query = entitiesContext.CreateQuery<Object>(queryString, new ObjectParameter("id", objectId));
foreach (Object result in query)
{
return result;
}
}
catch (EntitySqlException ex)
{
Console.WriteLine(ex.ToString());
}
}
return null;
I think the new CLR4 dynamic keywork might be the "nice" solution.
我认为新的 CLR4 动态键盘可能是“不错”的解决方案。
Thanks for all the responces.
感谢所有的回复。
回答by euwe
How about setting the root value as a string and then carry it around as a string until you need to convert it to the target type?
如何将根值设置为字符串,然后将其作为字符串携带,直到需要将其转换为目标类型?
回答by Marty
Once you get the reflected type, you can use Convert.ChangeType()
.
获得反射类型后,您可以使用Convert.ChangeType()
.
回答by user8097903
Type resultType = typeof(T);
IEnumerable<PropertyDescriptor> properties = TypeDescriptor.GetProperties(resultType).Cast<PropertyDescriptor>();
object instance = Activator.CreateInstance(resultType);
var objValue = "VALUE FOR HEADER";
var resultHeader = "HeaderName";
var prop = properties.Single(p => string.Equals(p.Name, resultHeader, StringComparison.InvariantCultureIgnoreCase));
var targetType = Nullable.GetUnderlyingType(prop.PropertyType) !=null Nullable.GetUnderlyingType(prop.PropertyType):prop.PropertyType;
objValue = Convert.ChangeType(objValue , targetType);
prop.SetValue(instance, objValue );
//return instance;
//返回实例;