Реализация метода с аргументом через интерфейс
Я хочу реализовать интерфейс IUpdateable который содержит метод Update. Суть метода в том, что он принимает 1 аргумент и присваивает свойства этого объекта "this-объекту". Пример реализации:
public interface IUpdateable
{
public void Update() { }
}
public class ClientCompany : ICloneable, IClient, IUpdateable
{
public int Id { get; set; }
public NameCompany Name { get; set; } = new NameCompany();
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public PropsCompany Props { get; set; } = new PropsCompany();
public BankInfo BankInfo { get; set; } = new BankInfo();
public void IUpdateable.Update(ClientCompany item)
{
Name = item.Name;
Address = item.Address;
Props = item.Props;
BankInfo = item.BankInfo;
}
}
public class ClientPerson : ICloneable, IClient, IUpdateable
{
public int Id { get; set; }
public NamePerson Name { get; set; } = new NamePerson();
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public PropsPerson Props { get; set; } = new PropsPerson();
public BankInfo BankInfo { get; set; } = new BankInfo();
public List<LegalCase> Cases { get; set; } = new List<LegalCase>();
public void Update(ClientPerson item)
{
Name = item.Name;
Address = item.Address;
Props = item.Props;
BankInfo = item.BankInfo;
}
}
В чем проблема:
Возникает исключение, поскольку у метода Update в интерфейсе 0 аргументов, хотя предполагается 1 аргумент:
public void EditClient<T>(T Client) where T : IUpdateable, IClient
{
//Создаем клон объекта
T editedClient = (T)Client.Clone();
//Создаем диалоговое окно и передаем в него ссылку на клон
WindowEditClient windowEditClient = new WindowEditClient(editedClient);
windowEditClient.ShowDialog();
//Если изменения прошли - вызываем метод Update
if (windowEditClient.DialogResult == true)
{
//ОШИБКА: Метод Update не содержит перегрузок, которые принимают 1 аргумент.
Client.Update(editedClient);
db.SaveChanges();
}
}
Если изменить метод в интерфейсе так чтобы он принимал 1 аргумент, то код компилируется без ошибок, но не работает. Дебаг показывает что C# теперь считает метод Update в интерфейсе полноценно реализованным методом и обращается к нему, а поскольку реализации там нет, то ничего не происходит.
public interface IUpdateable : ICloneable
{
public void Update(IUpdateable Item)
{ // Код исполняется здесь
}
}
public class ClientCompany : ICloneable, IClient, IUpdateable
{
public int Id { get; set; }
public NameCompany Name { get; set; } = new NameCompany();
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public PropsCompany Props { get; set; } = new PropsCompany();
public BankInfo BankInfo { get; set; } = new BankInfo();
public void Update(ClientCompany item)
{
// Код здесь не исполняется
Name = item.Name;
Address = item.Address;
Props = item.Props;
BankInfo = item.BankInfo;
}
}
Правка: Добавил имплементацию IClient
public interface IClient
{
public List<LegalCase> Cases { get; set; }
}
Ответы (1 шт):
Если в определении интерфейса вы указали модификатор public и тело метода { } - в данном случае пустое, - значит это метод интерфейса по умолчанию.
public void Update() { }
Вам, очевидно, нужен примерно следующий интерфейс:
public interface IUpdateable
{
void Update(ICommon item);
}
Где ICommon - интерфейс, содержащий общие свойства. (Я думал, IClient как раз содержит их.)
Вот определение этого интерфейса:
public interface ICommon
{
AddressesMultiple Address { get; set; }
BankInfo BankInfo { get; set; }
}
Теперь можно написать такой код:
public class ClientCompany : ICommon, IUpdateable
{
public int Id { get; set; }
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public BankInfo BankInfo { get; set; } = new BankInfo();
// остальные свойства
public void Update(ICommon item)
{
Address = item.Address;
BankInfo = item.BankInfo;
}
}
public class ClientPerson : ICommon, IUpdateable
{
public int Id { get; set; }
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public BankInfo BankInfo { get; set; } = new BankInfo();
// остальные свойства
public void Update(ICommon item)
{
Address = item.Address;
BankInfo = item.BankInfo;
}
}
Реализация может быть явной: void IUpdateable.Update(ICommon item).
Остальные свойства у этих классов разные, поэтому обновлять их таким способом не получится.
Можно использовать обобщённые типы (generics).
public interface IUpdateable<T>
{
void Update(T item);
}
public class ClientCompany : IUpdateable<ClientCompany>
{
public int Id { get; set; }
public NameCompany Name { get; set; } = new NameCompany();
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public PropsCompany Props { get; set; } = new PropsCompany();
public BankInfo BankInfo { get; set; } = new BankInfo();
public void Update(ClientCompany item)
{
Name = item.Name;
Address = item.Address;
Props = item.Props;
BankInfo = item.BankInfo;
}
}
public class ClientPerson : IUpdateable<ClientPerson>
{
public int Id { get; set; }
public NamePerson Name { get; set; } = new NamePerson();
public AddressesMultiple Address { get; set; } = new AddressesMultiple();
public PropsPerson Props { get; set; } = new PropsPerson();
public BankInfo BankInfo { get; set; } = new BankInfo();
public List<LegalCase> Cases { get; set; } = new List<LegalCase>();
public void Update(ClientPerson item)
{
Name = item.Name;
Address = item.Address;
Props = item.Props;
BankInfo = item.BankInfo;
}
}
Но в этом случае уже не получится, например, создать коллекцию наподобие List<IUpdateable>, в которую можно поместить классы обоих типов. И, соответственно, не будет работать ваш метод EditClient: в нем нельзя будет вызвать client.Update(editedClient);
Последняя итерация рефакторинга.
public interface IUpdateable
{
void Update(IUpdateable item);
}
public class ClientCompany : IUpdateable
{
// свойства опущены
public void Update(IUpdateable item)
{
ClientCompany client = (ClientCompany)item;
Name = client.Name;
Address = client.Address;
Props = client.Props;
BankInfo = client.BankInfo;
}
}
public class ClientPerson : IUpdateable
{
// свойства опущены
public void Update(IUpdateable item)
{
ClientPerson client = (ClientPerson)item;
Name = client.Name;
Address = client.Address;
Props = client.Props;
BankInfo = client.BankInfo;
}
}
Выглядит, честно говоря, криво. Но EditClient должен работать (не проверял).