C# 从基动态调用父方法失败,由于其保护级别不可访问
我正试图通过C# 从基动态调用父方法失败,由于其保护级别不可访问,c#,system.reflection,C#,System.reflection,我正试图通过从基类动态调用父类上的方法(这是动态的)。当(e)但我收到关于保护级别的错误时: An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll Additional information: 'Person.When(PersonCreated)' is inaccessible due to its protect
从基类动态调用父类上的方法(这是动态的)。当(e)
但我收到关于保护级别的错误时:
An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll
Additional information: 'Person.When(PersonCreated)' is inaccessible due to its protection level
Person
类是public类,将Person.When(PersonCreated)
更改为public会产生一个新错误与“Person.When(PersonCreated)”匹配的最佳重载方法具有一些无效参数
我想要实现的是通过基Apply(e)
方法将事件“路由”到父类的When(e)
方法
理想情况下,基中的When
方法不应是公共的
毫无疑问,我正在做一些非常愚蠢的事情。。。有什么想法吗?或者我需要用反射来代替
public abstract class EventSourcedAggregate
{
readonly List<DomainEvent> mutatingEvents = new List<DomainEvent>();
public readonly int UnmutatedVersion;
protected void Apply(DomainEvent e)
{
this.mutatingEvents.Add(e);
// the below line throws inaccessible protection level
(this as dynamic).When(e);
}
}
public abstract class DomainEvent
{
// snipped some time stamp stuff not relevant here
}
public class PersonCreated : DomainEvent
{
public readonly string Name;
public readonly string Address;
public PersonCreated(string name, string address)
{
Name = name;
Address = address;
}
}
public class Person : EventSourcedAggregate
{
public Person(string name, string address)
{
Apply(new PersonCreated(name, address));
}
public string Name { get; private set; }
public string Address { get; private set; }
void When(PersonCreated e)
{
Name = e.Name;
Address = e.Address;
}
}
static void Main(string[] args)
{
var user = new Person("sir button", "abc street");
}
公共抽象类eventSourceDaggerate
{
只读列表mutatingEvents=新列表();
公共只读int未修改版本;
受保护的无效应用(域事件e)
{
本.mutatingEvents.Add(e);
//下面的行抛出不可访问的保护级别
(这是动态的)。当(e);
}
}
公共抽象类DomainEvent
{
//剪下了一些与这里无关的时间戳
}
已创建的公共类PersonCreated:DomainEvent
{
公共只读字符串名称;
公共只读字符串地址;
public PersonCreated(字符串名称、字符串地址)
{
名称=名称;
地址=地址;
}
}
公共类人士:EventSourceDaggerate
{
公众人物(字符串名称、字符串地址)
{
申请(新创建的人员(姓名、地址));
}
公共字符串名称{get;private set;}
公共字符串地址{get;private set;}
当(个人创建时)无效
{
名称=e.名称;
地址=e.地址;
}
}
静态void Main(字符串[]参数)
{
var用户=新用户(“sir按钮”、“abc街”);
}
请注意,如果将when()
方法设置为公共
,则会出现不同的异常。也就是说,它现在可以访问,但您没有传递正确的类型
声明的When()
方法需要PersonCreated
的实例。但是您的呼叫站点只传递了DomainEvent
的一个实例
通常,dynamic
遵从通常在编译时完成的运行时行为。但除此之外,你必须遵循同样的规则。由于编译器不能保证DomainEvent
是PersonCreated
的实例,因此会出现错误(或者更具体地说,DomainEvent
与方法的已知重载不匹配)
您应该能够通过如下调用使代码正常工作:
(this as dynamic).When(e as dynamic);
也就是说,让运行时基于
e
的动态类型而不是其静态类型进行绑定。公开后,我会得到一个不同的错误。您应该查看错误:与“UserQuery.Person.When(UserQuery.PersonCreated)”匹配的最佳重载方法有一些无效参数
是否有理由强制转换为动态并调用该方法?为什么不把When
作为一个抽象方法并利用模板呢?如果我在时使用不同的参数When
即当(PersonCreated e)
和当(PersonMoved e)
和当(PersonMarried e)
等重载了超过1个参数,那么这样做行吗?我目前正在使用它来调度(它是有效的),但希望有一个编译安全的方式!vardispatchTo=o.GetType().GetMethod(“When”,BindingFlags.NonPublic | BindingFlags.Instance,null,new[]{e.GetType()},null);调用(o,新对象[]{e})代码>@g18c有一种编译安全的方法,但您需要给编译器更多的提示。例如,您需要编写Apply(personCreated,When),而不是Apply(personCreated)代码>,它将在您需要时正确地以方法为目标。这里有一个例子:。每次都要通过Where参数有点不好,但这会使其类型安全,并且可能会优化得更好。太棒了,谢谢大家,非常感谢你们,凌晨2点在这里,拔头发。这确实有效-因此类的内部工作可以得到保护,是否可以在不公开的情况下在父类中调用When()
?或者我需要通过反射来调用内部方法吗?不,protected
也不起作用。您可以通过internal
,但不清楚这是否足以保护该成员。一般来说,我认为您应该避免使用反射和dynamic
。这看起来是一个通过接口甚至强制转换更好地解决的问题<当您无法控制抽象的实现时(例如COM互操作,这是dynamic
首先存在的主要原因),code>dynamic
是一个很好的后备方案,但通常您会这样做,IMHO应该这样做。