首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将抽象类型转换为7种可能的其他类型

将抽象类型转换为7种可能的其他类型
EN

Stack Overflow用户
提问于 2021-07-01 12:38:31
回答 2查看 77关注 0票数 0

我有以下抽象类:

代码语言:javascript
运行
复制
public abstract partial class AsyncResult
{
}

以及从它继承的其他7个类(这里只有2个供参考):

代码语言:javascript
运行
复制
public partial class AsyncSearchResult : AsyncResult
{
    private SearchResult searchResultField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Namespace="urn:core_2020_2.platform.webservices.netsuite.com", Order=0)]
    public SearchResult searchResult
    {
        get
        {
            return this.searchResultField;
        }
        set
        {
            this.searchResultField = value;
        }
    }
}

public partial class AsyncGetListResult : AsyncResult
{
    private ReadResponseList readResponseListField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=0)]
    public ReadResponseList readResponseList
    {
        get
        {
            return this.readResponseListField;
        }
        set
        {
            this.readResponseListField = value;
        }
    }
}

我有一个返回抽象类型的方法,为了访问所需的属性,我需要将它转换为特定类型之一。

我无法在编译时找到一种方法来转换它,而不为每种情况编写7个it,并且经常重复代码。

感谢任何帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-01 12:43:20

为此,我喜欢使用访问者模式:

代码语言:javascript
运行
复制
public interface IAsyncResultVisitor
{
    void Accept(AsyncSearchResult searchResult);
    void Accept(AsyncGetListResult getListResult);
    // Etc...
}

public abstract partial class AsyncResult
{
    public abstract void Visit(IAsyncResultVisitor visitor);
}

public partial class AsyncSearchResult : AsyncResult
{
    // ...
    public override void Visit(IAsyncResultVisitor visitor) => visitor.Accept(this);
}

然后:

代码语言:javascript
运行
复制
public class AsyncResultProcessor : IAsyncResultVisitor
{
    public void ProcessAsyncResult(AsyncResult asyncResult)
    {
        asyncResult.Visit(this);
    }

    public void Accept(AsyncSearchResult searchResult)
    {
        // Access strongly-typed members of searchResult
    }

    public void Accept(AsyncGetListResult getListResult)
    {
        // Access strongly-typed members of getListResult
    }
}

请注意,switch语句和switch表达式在这里也有帮助,尽管它们不能确保您已经涵盖了每一种情况(就像访问者模式所做的那样):

代码语言:javascript
运行
复制
switch (asyncResult)
{
    case AsyncSearchResult searchResult:
        // ...
        break;
}
票数 3
EN

Stack Overflow用户

发布于 2021-07-01 14:30:55

我会用不同的方式实现访客。@canton7 7实现的问题是,数据必须知道人们应该如何使用它,但它只是普通的数据!

首先:AsyncResult应该有private protected构造函数,所以其他程序集都不能“实现”这个抽象类。

代码语言:javascript
运行
复制
public abstract class AsyncResult
{
    private protected AsyncResult() {}
}

public sealed class ResultOne : AsyncResult()
{
    public string Data { get; set; }
}
// 6 more to go

使接口匹配所有类型

代码语言:javascript
运行
复制
public interface IAsyncResultVisitor
{
    void Visit(AsyncResult result);
    void VisitResultOne(ResultOne result);
    void VisitResultTwo(ResultTwo result);
    // 5 more to go
}

并创建默认访问者,它将对每种包含访问策略的类型具有属性

代码语言:javascript
运行
复制
public sealed class LambdaAsyncResultVisitor : IAsyncResultVisitor
{
    public Action<ResultOne> OnVisitOne { get; set; } 
    public void VisitResultOne(ResultOne result)
    {
       if (OnVisitOne is null)
           throw new InvalidOperationException("...");
       OnVisitOne.Invoke(result);
    }
    // 6 more to go
}

这样我们就可以这样使用它了。

代码语言:javascript
运行
复制
AsyncResult result = ...;

string someString = "";
new LambdaAsyncResultVisitor
{
   OnVisitOne = r => someString = r.Data,
   OnVisitTwo = r => someString = "two",
   OnVisitThree => _ =>  throw new Exception("I know that is is impossible"),
}.Visit(result);

HandleSomeString(someString);

这比默认的访问者模式提供了更多的灵活性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68210359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档