Мне нужно сделать что-то подобное в С#. Но в Exec (объект) у меня возникла ошибка компиляции.
public class ParentClass { }
public class class1 : ParentClass
{
}
public class class2 : ParentClass
{
}
public class class3 : ParentClass
{
}
public class MasterClass
{
public void ExecutionMethod(ParentClass myObject)
{
//some code
Exec(myObject);
//some code
}
public void Exec(class1 obj)
{
//some code
}
public void Exec(class2 obj)
{
//some code
}
public void Exec(class3 obj)
{
//some code
}
}
Я решил использовать Reflection, но я думаю, что это должен быть лучший подход, кто-то может дать мне хорошую идею
Как отметил @ScottChamberlain в комментариях, у вас нет методов, которые принимают аргумент типа ParentClass
.
Взгляните на принцип замещения Лискова - если вы правильно выполнили свою реализацию, вы можете заменить экземпляр класса class1
для экземпляра ParentClass
, но обратное неверно.
Скорее всего, вам не нужны (или не хотят) перегрузки в любом случае. Просто ParentClass
будет абстрактным классом с абстрактным методом Execute
который должны реализовать все дочерние классы, тогда вы можете просто вызвать Execute
в классе непосредственно, не беспокоясь о перегрузках. Еще лучше, просто сделайте ParentClass
интерфейсом. (Это иногда называют шаблоном стратегии).
public interface IParent {
void Execute();
}
public class class1 : ParentClass {
//Execute method implementation
}
public class class2 : ParentClass {
// ...
}
public class class3 : ParentClass {
// ....
}
public class MasterClass
{
public void ExecutionMethod(IParent myObject)
{
//some code
myObject.Execute();
//some code
}
}
Я предлагаю вам взглянуть на объектно-ориентированные шаблоны проектирования. В частности, шаблон стратегии для этой проблемы. В любом случае, вы можете реализовать то, что хотите:
public interface IParent
{
void Exec();
}
public class Child1 : IParent
{
void Exec() { /*code*/ }
}
public class Child2 : IParent
{
void Exec() { /*code*/ }
}
public class Child3 : IParent
{
void Exec() { /*code*/ }
}
public class MasterClass
{
public void ExecutionMethod(IParent myObject)
{
//some code
myObject.Exec();
//some code
}
}
Вы также можете использовать абстрактный класс вместо интерфейса, если вы хотите, чтобы родительский класс имел некоторые функции для метода Exec - тогда дочерние классы должны были бы переопределить метод.
Ошибка, которую вы видите, является результатом того, что объекты class1,2,3 были выбраны как их родительский тип из-за подписи ExecutionMethod (xxx). И не имея переопределенного метода Exec, который принимает тип "ParentClass" в качестве аргумента.
Вероятно, самым простым способом является создание интерфейса:
IDomainObject{}.
public class ParentClass : IDomainObject { }
public void ExecutionMethod(IDomainObject myObject)
{
Exec(myObject);
}
Использование интерфейса таким образом предотвратит подавление во время вызова метода.
Вы можете использовать шаблон команды с инъекцией зависимостей. Я как бы даю вам идею ниже. Конкретная реализация вызовет выполнение на вашем ресивере (логика идет туда
public interface ICommand
{
void Execute();
}
public class Command1 : ICommand
{
public void Execute()
{
throw new NotImplementedException();
}
}
public class Command2 : ICommand
{
public void Execute()
{
throw new NotImplementedException();
}
}
public class Command3 : ICommand
{
public void Execute()
{
throw new NotImplementedException();
}
}
public class CommandManager
{
//you should use DI here to inject each concerete implementation of the command
private Dictionary<string, ICommand> _commands;
public CommandManager()
{
_commands = new Dictionary<string, ICommand>();
}
public void Execute(string key)
{
_commands[key].Execute();
}
}
Вам нужно использовать интерфейс здесь
Попробуйте изменить ParentClass
следующим образом:
public interface IParentClass{}
Затем сделайте каждый из своих классов таким, как это:
public class class1 : IParentClass
{
}
public class class2 : IParentClass
{
}
Затем в своем MasterClass попробуйте следующее:
public void ExecutionMethod(IParentClass myObject)
{
//some code
Exec(myObject);
//some code
}
public void Exec(IParentClass obj)
{
//some code
}
И затем вы можете передать любой из ваших классов, реализующих интерфейс IParentClass
.
Теперь в качестве улучшения - если вы хотите, чтобы каждая реализация IParentClass
имела некоторые методы и свойства, которые вы можете вызвать в своем методе Exec, сделайте это так:
public interface IParentClass
{
void DoTheThing();
}
Это заставит вас использовать этот метод в производных классах, поэтому, например, class1 будет выглядеть так:
public class class1 : IParentClass
{
public void DoTheThing()
{
// things get done...
}
}
public class class2 : IParentClass
{
public void DoTheThing()
{
// things get done a different way...
}
}
И теперь в вашем методе Exec вы можете вызвать так:
public void Exec(IParentClass obj)
{
obj.DoTheThing();
}
ParentClass
но у него нет перегрузки, которая принимаетParentClass
.