动态声明一个变量
Declaring a variable dynamically
我有这样一个简单的用户结构:
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;
}
}
继承基于他们可以执行的 Actions。该系统将不得不根据使用它的人以不同方式工作。
管理员可以浏览和购买以及随意处理订单和商品。
客户可以浏览购买。
访客只能浏览(当然 login/reg)。
要知道谁是我们的当前用户,我们需要 Authentication class
中的 属性 或字段,即 IUser
,这样任何人、管理员、客户和访客也可以在其中实例化。
问题是,当我只有这个 IUser 时,当我实例化时,我基本上什么也做不了。
所以问题是:我想加载该字段或 属性 并且我仍然想访问它的功能 - 但仅限给定用户可以访问的功能,所以如果管理员登录,我想要做管理员的工作。如果客户登录,我只希望能够列出货物等。这该怎么做?
编辑: 尝试反射
public class Guest : IUser
{
public Guest()
{
}
public object Get()
{
Type type = this.GetType();
var result = Activator.CreateInstance(type);
return result;
}
}
那个Get()
方法只给出一个object
但是如果它被一个Guest
调用,它必须是Guest。如果由 Admin
调用,则必须是 Admin。
我可以使用覆盖来做到这一点,但以后很难修改。
所以我希望这样:
(MyObject)Activator.CreateInstance(type);
其中 MyObject
如果是来宾调用则为来宾,如果是管理员调用则为 Admin。我错过了什么?当然,我尝试过泛型,但是当我实现接口时,它需要一个具体类型,所以基本上我需要在我所有的后代 类 中实现它。
根据我们在评论中讨论的内容,这里是我们服务器端游戏代码的直接复制粘贴。但要记住:如果您定义了 IUser
接口,但总是像 var customer = iUser as Customer
一样将其转换为适当的 class。你可能走错了路。我们仅在少数情况下使用以下代码。
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: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);
我得到的密码是 "asd"。
主要缺点:
由于动态,我无法使用 Intellisense。
解决方案 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);
}
}
这要求所有 classes 都有一个 Get
方法。
在我的例子中,我将在我的 IUser 界面中定义它,如下所示:
public interface IUser
{
T Get<T>() where T : class;
}
T 必须是 class 如果我稍后要使用 as
关键字。
而 Get
在我的 Guest 中的实现就像
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;
这里几乎没有任何优势。
我可以考虑用给定的 属性 值加载一个 class,但这与我创建的 IUser
的引用不同,肯定是 非常慢。
我有这样一个简单的用户结构:
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;
}
}
继承基于他们可以执行的 Actions。该系统将不得不根据使用它的人以不同方式工作。
管理员可以浏览和购买以及随意处理订单和商品。
客户可以浏览购买。
访客只能浏览(当然 login/reg)。
要知道谁是我们的当前用户,我们需要 Authentication class
中的 属性 或字段,即 IUser
,这样任何人、管理员、客户和访客也可以在其中实例化。
问题是,当我只有这个 IUser 时,当我实例化时,我基本上什么也做不了。
所以问题是:我想加载该字段或 属性 并且我仍然想访问它的功能 - 但仅限给定用户可以访问的功能,所以如果管理员登录,我想要做管理员的工作。如果客户登录,我只希望能够列出货物等。这该怎么做?
编辑: 尝试反射
public class Guest : IUser
{
public Guest()
{
}
public object Get()
{
Type type = this.GetType();
var result = Activator.CreateInstance(type);
return result;
}
}
那个Get()
方法只给出一个object
但是如果它被一个Guest
调用,它必须是Guest。如果由 Admin
调用,则必须是 Admin。
我可以使用覆盖来做到这一点,但以后很难修改。
所以我希望这样:
(MyObject)Activator.CreateInstance(type);
其中 MyObject
如果是来宾调用则为来宾,如果是管理员调用则为 Admin。我错过了什么?当然,我尝试过泛型,但是当我实现接口时,它需要一个具体类型,所以基本上我需要在我所有的后代 类 中实现它。
根据我们在评论中讨论的内容,这里是我们服务器端游戏代码的直接复制粘贴。但要记住:如果您定义了 IUser
接口,但总是像 var customer = iUser as Customer
一样将其转换为适当的 class。你可能走错了路。我们仅在少数情况下使用以下代码。
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: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);
我得到的密码是 "asd"。
主要缺点:
由于动态,我无法使用 Intellisense。
解决方案 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);
}
}
这要求所有 classes 都有一个 Get
方法。
在我的例子中,我将在我的 IUser 界面中定义它,如下所示:
public interface IUser
{
T Get<T>() where T : class;
}
T 必须是 class 如果我稍后要使用 as
关键字。
而 Get
在我的 Guest 中的实现就像
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;
这里几乎没有任何优势。
我可以考虑用给定的 属性 值加载一个 class,但这与我创建的 IUser
的引用不同,肯定是 非常慢。