C#:动态转换类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/566510/
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
C#: Casting types dynamically
提问by MK_Dev
I currently have this type of code:
我目前有这种类型的代码:
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
if (MainObject is SomeClassType1)
{
SomeClassType1 HelpObject = (SomeClassType1)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
else if (MainObject is SomeClassType2)
{
SomeClassType2 HelpObject = (SomeClassType2)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
}
Assuming that SomeClassType1 and SomeClassType2 have the same set of properties that I want to assign (although they may differ in other ones), is it possible to dynamically cast MainObject to the appropriate type and then assign the value, without duplicating the code? This is what I would like to see in the end:
假设 SomeClassType1 和 SomeClassType2 具有我想要分配的相同属性集(尽管它们在其他属性中可能不同),是否可以将 MainObject 动态转换为适当的类型,然后分配值,而无需重复代码?这是我最终希望看到的:
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
Type DynamicType = null;
if (MainObject is SomeClassType1)
{
DynamicType = typeof(SomeClassType1);
}
else if (MainObject is SomeClassType2)
{
DynamicType = typeof(SomeClassType2);
}
DynamicType HelpObject = (DynamicType)MainObject;
HelpObject.Property1 = Arg1;
HelpObject.Property2 = Arg2;
}
And obviously C# complains about not being able to find DynamicType:
显然 C# 抱怨找不到 DynamicType:
The type or namespace name 'DynamicType' could not be found (are you missing a using directive or an assembly reference?)
找不到类型或命名空间名称“DynamicType”(您是否缺少 using 指令或程序集引用?)
Is something like this possible in C# 2.0? If it's more messy than my current code, than I see no point in doing this, but I'm very interested to find out. Thanks!
在 C# 2.0 中可能有这样的事情吗?如果它比我当前的代码更混乱,那么我认为这样做没有意义,但我很想知道。谢谢!
EDIT: Just to clarify, I perfectly understand that implementing an interface is the most appropriate and probably correct solution. That said, I'm more interested in seeing how to I could do it without implementing an interface. Thanks for great replies!
编辑:只是为了澄清,我完全理解实现接口是最合适且可能正确的解决方案。也就是说,我更感兴趣的是了解如何在不实现接口的情况下做到这一点。感谢您的精彩回复!
采纳答案by Joel Coehoorn
It looks like both of the types you care about implement the same two properties. In that case, what you want to do is define an interface for those properties:
看起来您关心的两种类型都实现了相同的两个属性。在这种情况下,您要做的是为这些属性定义一个接口:
public interface IMyInterface
{
public Foo Property1 {get; set;}
public Bar Property2 {get;set;}
}
Then, make sure each of your classes tell the compiler that they implement that new interface. Finally, use a generic method with a type argument that is constrained to that interace:
然后,确保您的每个类都告诉编译器它们实现了该新接口。最后,使用一个类型参数被限制到该接口的泛型方法:
private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2)
where T : IMyInterface
{
MainObject.Property1 = Arg1;
MainObject.Property2 = Arg2;
}
Note that even with the extra code to declare the interface, these snippets still end up shorter than either one of the snippets you posted in the question, and this code is much easier to extend if the number of types you care about increases.
请注意,即使使用额外的代码来声明接口,这些片段最终仍然比您在问题中发布的任何一个片段都要短,并且如果您关心的类型数量增加,则此代码更容易扩展。
回答by JaredPar
Essentially what you're doing here is writing a switch statement based on the type fo the object. There is no inherently good way to do this other than your first example (which is tedious at best).
本质上,您在这里所做的是根据对象的类型编写 switch 语句。除了您的第一个示例(充其量是乏味的)之外,没有固有的好方法可以做到这一点。
I wrote a small framework for switching on types that makes the syntax a bit more concise. It allows you to write code like the following.
我编写了一个用于切换类型的小框架,使语法更加简洁。它允许您编写如下代码。
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(
() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(
x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(
() => textBox1.Text = "Not sure what is hovered over"));
Blog Post: http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx
博客文章:http: //blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx
回答by Craig
Instead of trying to cast, perhaps you could try setting the properties using reflection.
与其尝试强制转换,也许您可以尝试使用反射设置属性。
回答by Mehrdad Afshari
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2)
{
Type t = MainObject.GetType();
t.GetProperty("Property1").SetValue(MainObject, Arg1, null);
t.GetProperty("Property2").SetValue(MainObject, Arg2, null);
}
回答by Autodidact
Will you be able to make changes to SomeClassType1, SomeClassType2 etc? If yes then I will suggest that you create an interface containing your common properties and then typecast to this interface within FillObject()
to set the properties.
您是否能够对 SomeClassType1、SomeClassType2 等进行更改?如果是,那么我建议您创建一个包含常用属性的接口,然后将其类型转换为该接口FillObject()
以设置属性。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SO566510
{
interface IMyProperties
{
int Property1 { get; set; }
int Property2 { get; set; }
}
class SomeClassType1 : IMyProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class SomeClassType2 : IMyProperties
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var obj1 = new SomeClassType1();
var obj2 = new SomeClassType2();
FillObject(obj1, 10, 20);
FillObject(obj2, 30, 40);
}
private static void FillObject(IMyProperties objWithMyProperties
, int arg1, int arg2)
{
objWithMyProperties.Property1 = arg1;
objWithMyProperties.Property2 = arg2;
}
}
}
回答by airportyh
Some ideas:
一些想法:
- Have both types inherit from the same type that have the common properties
- Have both types implement the same interface that have the common properties
- Use reflection to set the properties rather than setting them directly(this is probably more ugly than it's worth)
- Use the new dynamicfeature, I haven't tried this, but looks like it might address your issue
- 让两种类型都继承自具有共同属性的同一类型
- 让两种类型都实现具有共同属性的相同接口
- 使用反射来设置属性而不是直接设置它们(这可能比它的价值更丑陋)
- 使用新的动态功能,我还没有尝试过,但看起来它可能会解决您的问题
回答by Michael Ceranski
I am dynamically casting objects using Reflection in an ASP.NET MVC app. Basically I enumerate the properties of a class, find the corresponding value in the data store and dynamically cast the value and assign it to the object instance. See my blog post Dynamic Casting with .NET
我在 ASP.NET MVC 应用程序中使用反射动态转换对象。基本上我枚举一个类的属性,在数据存储中找到相应的值并动态转换该值并将其分配给对象实例。请参阅我的博客文章 Dynamic Casting with .NET