我有一个简单的用户结构:
public Guest() : IUser
{
}
[Table("Users")]
public class Customer : Guest
{
[Key]
public string UserName { get; set; }
public string Password { get; set; }
public string Address { get; set; }
public bool IsAdmin { get;protected set; }
public UserCart UserCart { get; private set; }
public Customer()
{
}
public Customer(string username, string password, string address)
{
this.Address = address;
this.UserName = username;
this.Password = password;
this.IsAdmin = false;
this.UserCart = new UserCart();
}
}
public class Admin : Customer
{
public Admin()
{
}
public Admin(string username, string password,
string address)
: base(username, password, address)
{
IsAdmin = true;
}
}
继承基于他们可以做的动作。系统必须根据使用者的不同而有所不同。
管理员可以浏览,购买和处理订单和商品。
客户可以浏览和购买。
访客只能浏览(当然还有登录/注册)。
要知道我们当前的用户是谁,我们需要Authentication class
内IUser
的属性或字段,因此任何人,管理员,客户和访客都可以实例化在里面。
问题是,当我只有这个IUser时,当我实例化时,我基本上什么都不做。
所以问题:我想加载该字段或属性,我仍然想要访问它的功能 - 但只有那些给定用户可以,所以如果管理员登录,我想做管理员&#39的工作。如果客户登录,我只想能够列出货物等。这该怎么做?
编辑尝试使用反射
public class Guest : IUser
{
public Guest()
{
}
public object Get()
{
Type type = this.GetType();
var result = Activator.CreateInstance(type);
return result;
}
}
Get()
方法仅提供object
,但如果Guest
调用它,则必须为访客。如果由Admin
调用,则必须为Admin。
我可以使用覆盖来做到这一点,但以后很难修改。
所以我希望如此:
(MyObject)Activator.CreateInstance(type);
如果来自访客,管理员调用来自MyObject
的是来宾,则来自管理员。我错过了什么?当然我尝试了泛型,但是当我实现接口时需要一个具体的类型,所以基本上我需要在所有后代类中实现它。
答案 0 :(得分:1)
根据我们在评论中谈到的内容,这里是我们服务器端游戏代码的直接复制粘贴。但请记住:如果您定义var customer = iUser as Customer
接口,但总是将其转换为适当的类,如public void DoSomethingWithBattleUnit(BattleUnit bUnit){
if(bUnit.UnitType==typeof(BattleMonster)){
var bMonster = bUnit as BattleMonster;
bMonster.ActivateAI();
}
public abstract class BattleUnit {
public abstract Type UnitType { get; }
}
public class BattleMonster : BattleUnit {
/// <summary>
/// Current type for this class.
/// </summary>
/// <remarks>Micro optimization instead of using this.GetType() or calling typeof(BattleMonster) each time.</remarks>
static readonly Type Type = typeof(BattleMonster);
public override Type UnitType => Type;
}
public class BattleUser : BattleUnit, IUser {
/// <summary>
/// Current type for this class.
/// </summary>
/// <remarks>Micro optimization instead of using this.GetType() or calling typeof(BattleUser) each time.</remarks>
private static readonly Type Type = typeof(BattleUser);
public override Type UnitType => Type;
}
。你可能走错了路。我们仅在几次使用以下代码。
{{1}}
答案 1 :(得分:0)
这实际上是可能的,甚至不是那么难。
解决方案1:dynamic
关键字
我有这个界面IUser
,其中有一个属性
public interface IUser
{
dynamic Instance { get; }
}
我只在祖先中实现,在我的情况下是来宾:
public class Guest : IUser
{
public Guest()
{
}
public dynamic Instance
{
get
{
return this;
}
}
}
这样我就可以在Program.cs中声明一个IUser
:
IUser user = new Admin("wat", "asd", 012);
Console.WriteLine(user.Instance.PW);
我得到的密码是&#34; asd&#34;。
市长的缺点:
由于动态,我无法使用智能感知。
解决方案2:使用扩展方法
这个实现和使用都有点丑陋,但仍然可以利用Intellisense的强大功能。
所以这里我们有这个很好的扩展方法:
public static class Extensions
{
public static T Get<T>(this T input) where T:class
{
Type t = input.GetType();
MethodInfo method = t.GetMethod("Get");
MethodInfo generic = method.MakeGenericMethod(t);
return (T)generic.Invoke(input,null);
}
}
这要求所有类都有Get
方法。
在我的情况下,我将在我的IUser界面中定义它,如下所示:
public interface IUser
{
T Get<T>() where T : class;
}
如果我稍后要使用as
关键字,则必须是T类。
我的访客中Get
的实施就像
public T Get<T>() where T:class
{
var _instance = this;
return _instance as T;
}
当然,它并不要求后代再次实施Get
。
完成后我们可以获得当前类型:
IUser adm = new Admin("wut", "mehpw", 1000);
var stuff = adm.Get<Admin>().Name;
<强>缺点:强>
我必须知道我使用的对象的类型,所以基本上这不仅仅是使用
var stuff = (adm as Admin).Name;
这里几乎没有任何边缘。
我可以想到基本上加载一个具有给定属性值的类,但这不会与我创建的IUser
相同,并且肯定会非常慢。< / p>