首页 > 解决方案 > 使用动态值调用抽象基类方法

问题描述

我试图从继承的抽象基类中调用一个带有动态变量的方法,但它因溢出异常而失败。

可以在以下位置测试可运行版本(带有布尔值): https ://dotnetfiddle.net/hSfsZl

可以在以下位置找到崩溃的可运行版本(具有动态值): https ://dotnetfiddle.net/qXlMZD

public static void Main(string[] args)
{

    dynamic processed = true;
    // this works though
    //bool visible = true; 
    var data = new TemplateData<string>();
    var dataProcessor = new TemplateDataProcessor<string>(data);
    dataProcessor.Process(processed);

    Console.WriteLine(data.Processed);
}

public class Data : IData
{
    public bool Processed { get; set; }
}

public interface IData
{
    bool Processed { get; set; }
}

public abstract class DataProcessorBase<TData, TDataBuilder>
    where TDataBuilder : DataProcessorBase<TData, TDataBuilder>
    where TData : IData
{

    public TData Data { get; set; }

    public DataProcessorBase(TData data)
    {
        Data = data;
    }

    public TDataBuilder Process(bool value)
    {
        Data.Processed = value;

        return this as TDataBuilder;
    }
}


public abstract class DataProcessor<TData, TDataBuilder> : DataProcessorBase<TData, TDataBuilder>
    where TDataBuilder : DataProcessor<TData, TDataBuilder>
    where TData : IData
{
    public DataProcessor(TData data)
        : base(data)
    {

    }
}

public interface ITemplateData<T> : IData
    where T : class
{
    string Template { get; set; }
}

public class TemplateData<T> : ITemplateData<T>
    where T : class
{
    public string Template { get; set;  }

    public bool Processed { get; set; }
}

public class TemplateDataProcessor<T> : DataProcessor<ITemplateData<T>, TemplateDataProcessor<T>>
//public class TemplateDataProcessor<T> : DataProcessorBase<ITemplateData<T>, TemplateDataProcessor<T>>
    where T : class
{
    public TemplateDataProcessor(ITemplateData<T> data)
        : base(data)
    {
    }
}

使用布尔值调用dataProcessor.Process(processed);按预期工作,但使用等于 true 的动态变量调用它会引发异常。另外,从基抽象类继承解决了这个问题

public class TemplateDataProcessor<T> : DataProcessorBase<ITemplateData<T>, TemplateDataProcessor<T>>

为什么这不起作用?此外,为什么从基类继承 - DataProcessorBase- 甚至可以使用动态值?以下继承破坏了代码有什么问题:

public abstract class DataProcessor<TData, TDataBuilder> : DataProcessorBase<TData, TDataBuilder>

是否可以通过满足以下所有要求来解决此问题:

  1. 不要将任何方法从类DataProcessorBase移到类或更改它们的代码,例如不允许DataProcessor更改为。Process(dynamic value)
  2. 调用dataProcessor.Process将使用动态进行,即不能强制 API 的最终用户使用 bool 而不是动态。

标签: c#

解决方案


这似乎是.NET本身的问题-在动态dispathc中,就像调用堆栈一样:它只是重复

TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
TypeManager.SubstTypeCore(type, pctx)
TypeManager.SubstTypeArray(taSrc, pctx)
TypeManager.SubstTypeCore(type, pctx)
AggregateType.GetBaseClass()
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
TypeManager.GetAggregate(agg, typeArgsAll)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
TypeManager.GetAggregate(agg, atsOuter, typeArgs)
AggregateSymbol.getThisType()
SymbolTable.AddAggregateToSymbolTable(parent, type)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.GetConstructedType(type, agg)
SymbolTable.LoadSymbolsFromType(originalType)
SymbolTable.CreateInheritanceHierarchyList(type)
SymbolTable.PopulateSymbolTableWithName(name, typeArguments, callingType)
PopulateSymbolTableWithPayloadInformation(payload, callingType, arguments)
BindCore(payload, parameters, args, deferredBinding)
Bind(payload, parameters, args, deferredBinding)
BinderHelper.Bind(action, binder, args, arginfos, onBindingError)
CSharpInvokeMemberBinder.FallbackInvokeMember(target, args, errorSuggestion)
DynamicMetaObject.BindInvokeMember(binder, args)
InvokeMemberBinder.Bind(target, args)
DynamicMetaObjectBinder.Bind(args, parameters, returnLabel)
CallSiteBinder.BindCore<System.Action<System.Runtime.CompilerServices.CallSite, Program.TemplateDataProcessor<string>, object>>(site, args)
UpdateDelegates.UpdateAndExecuteVoid2<Program.TemplateDataProcessor<string>, object>(site, arg0, arg1)
Program.Main(args)

我会向微软报告


推荐阅读