调用具有动态值的抽象基类方法

时间:2019-05-23 07:18:09

标签: c#

我正在尝试从具有动态变量的继承的抽象基类中调用方法,但是由于出现溢出异常而失败。

可以在以下位置测试可运行版本(具有bool值): 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而不是动态方式。

1 个答案:

答案 0 :(得分:0)

这似乎是.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)

我会报告给微软