从另一个实例创建新对象

B-M*_*B-M 2 .net c#

我发现了类似的问题,但我仍然遇到麻烦:

  1. 动态创建<Type>的对象
  2. 从Type中获取新的对象实例

- 希望能更好地描述这个问题吗?----

当我调用Web服务时,带回的响应是xml文档.该文档定义了要返回的类,然后通过将xml反序列化为8种不同类型中的1种来设置所有值.

现在,当我这样做时,receipt.Item我得到返回的类型; 但由于使用Web服务调用设置接口的方式,除非我输入强制转换,否则我无法访问任何项成员变量receipt.Item.这是通过开关盒完成的.但我希望在switch case之外创建对象并在switch case中初始化它,以便稍后我可以在代码中访问它.这就是为什么我不在switch case中创建那种类型的新对象并在那里工作(或调用函数).


我有一个来自我正在调用的Web服务的总体返回类型的响应,并且Web服务可以有8种不同的结果类型.我需要创建一个可以返回的8种返回类型中的1种的实例.

所以这是一个更直观的结构

Response
     accountUpdaterRespType
     endOfDayRespType
     flexCacheRespType
Run Code Online (Sandbox Code Playgroud)

响应对象的代码:

public partial class Response {

    private object itemField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("AccountUpdaterResp", typeof(accountUpdaterRespType))]
    [System.Xml.Serialization.XmlElementAttribute("EndOfDayResp", typeof(endOfDayRespType))]
    [System.Xml.Serialization.XmlElementAttribute("FlexCacheResp", typeof(flexCacheRespType))]
    public object Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我得到Response的返回对象时,我可以通过执行来获取类型responseObject.Item并执行GetType()该操作.这就是我可以尝试输入一个新对象的方法.

我必须这样做,因为当我这样responseObject.Item做时,我无法访问不同对象类型中的不同变量.所以我试图在开关盒中输入一个新对象,如下所示:

object newReceipt = Receipt.GetType(); //this is where I would get the type I assume?? I don't know

string type = Receipt.Item.GetType().ToString();

switch (type)
{
    case "accountUpdaterRespType":
        newReceipt = (accountUpdaterRespType)Receipt.Item;

        break;
    case "endOfDayRespType":
        newReceipt = (endOfDayRespType)Receipt.Item;
        break;
    case "flexCacheRespType":
        newReceipt = (flexCacheRespType)Receipt.Item;
        break;
}
Run Code Online (Sandbox Code Playgroud)

Nik*_*vić 5

在回答之前我会尝试重述你的问题.

您正在尝试创建对现有实例的类型化引用.您已经有一个对象的实例,它以类型的变量保存object,但是为了能够访问成员而想要将其强制转换.

通过在代码中获取变量类型,您仍然无法在开发时访问对象成员.

使用字符串检查对象类型不是一个好主意.您的问题的工作解决方案将遵循

// as is a type of cast. if Receipt is of type cast,
// it will return an object and put it into accountUpdater
// variable. If Receipt is not of that type, it will place null
// into accountUpdater variable
var accountUpdater = Receipt.Item as accountUpdater;
if (accountUpdater != null)
{
    // Do something with account updater here. E.g.
    Console.WriteLine(accountUpdater.SomeAccountUpdaterProperty);
}
var endOfDayResp = Receipt.Item as endOfDayRespType;
if (endOfDayResp != null)
{
    // Do something with endOfDayResp here
}   
var flexCache = Receipt.Item as flexCacheRespType;
if (flexCache != null)
{
    // Do something with flex cache here
} 
Run Code Online (Sandbox Code Playgroud)

你明白了.请注意,这不是编写代码的好方法.上面的示例只是为了让您启动并运行.您应该熟悉面向对象的编程概念,特别是对于这种情况,多态性.

另一种(基本相同)处理这种方法的方法是:

var accountUpdater = Receipt.Item as accountUpdater;
if (Receipt.Item is accountUpdater)
    HandleAccountUpdater((accountUpdater)Receipt.Item);
else if (Receipt.Item is endOfDayRespType)
    HandleEndOfDay((endOfDayRespType)Receipt.Item);
else if (Receipt.Item is flexCacheRespType)
    HandleFlexCache((flexCacheRespType)Receipt.Item);
else
    throw new InvalidArgumentException("Unexpected parameter type");
Run Code Online (Sandbox Code Playgroud)

你是对的,多态性是一种解决方案,在这种情况下,对象具有相似的特征,需要以类似的方式处理.上面的两个解决方案是您无需了解C#语言的最佳方法.第二种解决方案可以更好地分离责任


您可以使用反射获得更通用的解决方案.使用System.Reflection您的方法可以对处理程序方法进行更通用的解析.以下为例:

你有Response像你描述的对象.您还有一个可以处理不同类型对象的类.例如:

public class ResponseHandler
{
    public void Handle(accountUpdater parameter) { /* */ }
    public void Handle(endOfDayRespType parameter) { /* */ }
    public void Handle(flexCacheRespType parameter) { /* */ }
    public void Handle(TypeD parameter) { /* */ }
    public void Handle(TypeE parameter) { /* */ }
    ...
}
Run Code Online (Sandbox Code Playgroud)

收到响应后,您将能够确定动态调用哪个处理程序,而无需手动添加每个类型,如下所示:

var handler = new ResponseHandler();
var handlerClassType = typeof(ResponseHandler); // This is how you get Type object from a type. Unlike, `GetType` on objects
var paramType = Response.Item.GetType();
// Get me method which is named Handle and takes parameters in parameter array
// handlerMethod will be of type MethodInfo. This is basically a descriptor of a
// method. Not a pointer to a method or some such...
var handlerMethod = handlerClassType.GetMethod("Handle", new Type[] { paramType });
// Throw exception if we don't know how to handle it
if (handlerMethod == null)
    throw new Exception("Handler not found for received response type");
// Invoke the handler. We need to provide the method descriptor with object which
// should execute the method, and parameters that the method takes
handlerMethod.Invoke(handler, new object[] { Response.Item });
Run Code Online (Sandbox Code Playgroud)

这是在SO编辑器中写的,所以它可能不会立即运行:)