Другой вариант (и моя личная ссылка) заключается в том, чтобы просто поместить System.Web.Script.Serialization.ScriptIgnoreAttribute
в члены класса модели, которые вы не хотите сериализовать (или создать неявно-конвертируемый класс DTO для того же). 1002 *
Ex:
using System.Web.Script.Serialization;
public class User
{
[ScriptIgnore]
public int ID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Таким образом, вам не нужно определять специальный интерфейс, вы можете поместить эти метаданные прямо в вашу модель.
Обновление: Очевидно, что это не вариант, потому что класс является производным классом и его членами из (неизменяемого) базового класса, который следует скрыть.
С помощью можно динамически генерировать класс так, как вы хотите, используя Emit
или динамическую прокси-библиотеку, такую как Castle, но это будет очень громоздко. Если вы можете, я действительно рекомендую использовать простой прокси-класс:
public class UserResult
{
public UserResult(User user)
{
Username = user.Username;
Password = user.Password;
}
public string Username { get; set; }
public string Password { get; set; }
}
Или, если вы действительно не можете справиться с этим, вы можете создать «универсальный» прокси-экземпляр:
static class ProxyInstantiator
{
public static TProxy CreateProxy<TProxy>(object source)
where TProxy : new()
{
TProxy proxy = new TProxy();
CopyProperties(source, proxy);
return proxy;
}
protected static void CopyProperties(object source, object dest)
{
if (dest == null)
{
throw new ArgumentNullException("dest");
}
if (source == null)
{
return;
}
Type sourceType = source.GetType();
PropertyInfo[] sourceProperties =
sourceType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
Type destType = dest.GetType();
PropertyInfo[] destProperties =
destType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
var propsToCopy =
from sp in sourceProperties
join dp in destProperties on sp.Name equals dp.Name
select new { SourceProperty = sp, DestProperty = dp };
foreach (var p in propsToCopy)
{
object sourceValue = p.SourceProperty.GetValue(o, null);
p.DestProperty.SetValue(dest, sourceValue, null);
}
}
}
Тогда вы можете написать простой прокси класс (не интерфейс):
public class UserResult
{
public string Username { get; set; }
public string Password { get; set; }
}
И вызвать его в методе контроллера следующим образом:
User someUser = GetSomeUser();
UserResult result = ProxyInstantiator.CreateProxy<UserResult>(someUser);
Предупреждение об этом:
Это не учитывает индексированные свойства и завершится ошибкой, если таковые имеются. Он не учитывает «глубокое копирование» - если ваш исходный класс содержит ссылочные типы, он будет только копировать ссылки - возможно, это то, что вы хотите, а может и нет.
Лично я бы выбрал первый подход и просто создавал отдельные прокси-классы без универсального прокси, потому что, если я сделаю ошибку, я бы предпочел ошибку времени компиляции, чем ошибку времени выполнения. Но вы спросили, так что вы идете!