Вы не можете «перевести» функцию. Вы должны реализовать его из-за сильной типизации. Что вам нужно, это переводчик ADTO в А, который является тривиальным:
private A Translate(ADTO adto)
{
return new A() { Id = adto.Id, Name = adto.Name);
}
Тогда вы должны понимать, что вы на самом деле делаете. «Функция» - это выполнение по данным, это не сами данные. Таким образом, вам нужны две реализации, но они идентичны:
Func<A, bool> funcA = (a => a.Id == 1);
Func<ADTO, bool> funcADTO = (adto => adto.Id == 1);
Затем вам необходимо объединить их. Это настоящий преступник. Что вам нужно, чтобы сообщить компилятору, кто есть кто, выбрать один из этих случаев (только один, а не все из них):
A extends ADTO
ADTO extends A
A extends AbstractDataTransferObject, ADTO extends AbstractDataTransferObject
A implements IDataTransferObject, ADTO implements IDataTransferObject
Что бы посоветовать пойти на абстрактную версию, он имеет ряд преимуществ , В этот момент вы можете сделать это:
Func<AbstractDataTransferObject, bool> f = (adto => adto.Id == 1);
И использовать одну реализацию функции для всех производных, A и ADTO включены.
Очевидно, что абстрактная версия будет содержать общие свойства, то есть ВСЕ, которые вы указали: Id и Name. Я понимаю, что у вас будет еще много свойств и типов в реальном мире.
Вы действительно хотите отвлечь функциональность DTO от полезной нагрузки, чтобы вы могли реализовать общий репозиторий. Это то, что я сделал много лет назад, по крайней мере. Впоследствии проблема заключается в том, чтобы вводить lambdas для фильтрации данных независимо от производного типа, но это возможно.
Рано или поздно вы увидите, что вы должны понимать очень (ОЧЕНЬ) хорошо эти аргументы: covariance and contravariance
Я могу дать вам немного больше помощи:
http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
EDIT 2:
Чтобы ответить на комментарий, как я реализовал CRUD: я этого не сделал.
CRUD - это концепция DAO, как и DTO. В моем коде я использовал шаблон хранилища и единицу работы, которые являются обобщением и обойтись без фасада.
Это быстрая ссылка, чтобы объяснить разницу: http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/
Хранилище используется следующим образом:
public List<Customer> GetOlderThan(int minimumAge, bool lazy)
{
using(Repository<Customer> repo = RepositoryFactory.Create<Customer>(lazy))
{
return repo.Retrieve(c => c.Age >= minimumAge);
}
}
Как вы можете видеть в 3-х строк можно реализовать запрос, который транслируется в SQL :
SELECT * FROM Customers WHERE Age >= @minimumAge;
окончательной проблемы при реализации унифицированного хранилища является инъекцией Filte r предикат. Указатель на решение является то, что предикат действительно что-то вроде этого:
Func<bool, T>
Где Т фактический тип объекта (например, Customer
). Для запроса клиентов будет:
Func<bool, Customer>
Родовое хранилище будет тогда:
Repository<Customer>
Тем не менее, осуществление Repository<T>
является ванну крови, потому что вы должны получить все объекты из уникального класса (AbstractDomainObject
в моем случае), и это должно быть совместимым с фактической структурой Entity Framework.
The AbstractDomainObject
это почти так же, Вы писали:
public abstract class AbstractDomainObject
{
private int _id = -1;
public int ID
{
get
{
if (_id == -1)
{
throw new InvalidOperationException("domain object not yet persisted");
}
return _id;
}
set
{
if (_id != -1)
{
throw new InvalidOperationException("domain object already persisted");
}
_id = value;
}
}
public bool IsPersisted
{
get
{
return _id != -1;
}
}
}
В какой-то момент, ковариации и контрвариантность становится очень сложным, когда у вас есть AbstractFactory
, Repository<T>
и AbstractDomainObject
.
Измените 'public class ADTO' на' public class ADTO: A', и все готово;) Можете ли вы каким-либо образом преобразовать A в ADTO? (Я имею в виду, что вам не нужно вручную переписывать значения из одного в другое), подразумевается ли явное или явное литье? –
Почему бы вам просто не скопировать свойства? Кажется тривиальным. Должна быть причина, по которой вы не можете этого сделать. – usr
@AleksandarToplek DTO в этом примере - это сервисные контракты, а POCO - мои классы EF. Это преобразование выполняется в отдельном слое. Прямой связи между классами EF и контрактами нет. Работа выполняется в этом специализированном слое. – Olinad