动态声明变量

时间:2017-04-09 10:13:03

标签: c# backend code-organization

我有一个简单的用户结构:

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 classIUser的属性或字段,因此任何人,管理员,客户和访客都可以实例化在里面。 问题是,当我只有这个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的是来宾,则来自管理员。我错过了什么?当然我尝试了泛型,但是当我实现接口时需要一个具体的类型,所以基本上我需要在所有后代类中实现它。

2 个答案:

答案 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>