Another option (and my personal pereference) would be to simply put System.Web.Script.Serialization.ScriptIgnoreAttribute
on the members of the model class that you don't want serialized (or create an implicitly-convertible DTO class to do the same thing).
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; }
}
That way you don't need to define a special interface, you can put this metadata right in your model.
Update: Apparently that's not an option because the class is a derived class and it's members from the (unmodifiable) base class that should be hidden.
It is possible to dynamically generate a class the way you want, either using Emit
or a dynamic proxy library like Castle, but it's going to be very cumbersome. If you can, I would really recommend to use a simple proxy class instead:
public class UserResult
{
public UserResult(User user)
{
Username = user.Username;
Password = user.Password;
}
public string Username { get; set; }
public string Password { get; set; }
}
Or, if you really can't deal with maintaining this, you can build a "generic" proxy instantiator:
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);
}
}
}
Then you can write a simple proxy class (not interface):
public class UserResult
{
public string Username { get; set; }
public string Password { get; set; }
}
And invoke it in a controller method like this:
User someUser = GetSomeUser();
UserResult result = ProxyInstantiator.CreateProxy<UserResult>(someUser);
A word of caution about this:
This does not take into account indexed properties and will fail if there are any of those. It does not take into account "deep copying" - if your source class contains reference types, it will only copy the references - maybe that's what you want, maybe it isn't.
Personally, I'd take the former approach and just build individual proxy classes without the generic proxy, because if I make a mistake, I'd prefer a compile-time error over a runtime error. But you asked, so there you go!