動的

2017-04-09 57 views
1

私はこのようなユーザーの簡単な構造を有しています。誰がそれを使用するかによって、システムは異なった動作をする必要があります。動的

アドミニストレーターは、閲覧や購入ができ、注文や商品を混乱させることがあります。

お客様は閲覧して購入することができます。

ゲストは閲覧のみできます(もちろんログイン/ reg)。

IUserであるAuthentication classのプロパティまたはフィールドが必要なので、誰でも管理者、顧客、およびゲストをインスタンス化することができます。 問題は、私はこのIUserだけを持っているとき、私はインスタンス化するとき、私は基本的に何もすることはできません。

質問:私はそのフィールドやプロパティをロードしたいが、それでもその機能にアクセスしたいが、指定されたユーザーだけがアクセスできるので、管理者がログインしている場合は管理者の仕事をしたい。顧客がログインしている場合は、商品などを一覧表示できるだけですみます。これを行う方法?

EDIT:Get()方法のみobjectを与えるが、それはGuestによって呼び出された場合、それはユーザーレビューする必要があることを反映

public class Guest : IUser 
    { 
     public Guest() 
     { 

     } 

     public object Get() 
     { 
      Type type = this.GetType(); 
      var result = Activator.CreateInstance(type); 
      return result; 
     } 
    } 

としよう。 Adminによって呼び出された場合は、Adminでなければなりません。 オーバーライドを使用してこれを行うことはできますが、後で変更することは困難です。

だから私はこれをしたい:ゲスト、管理者から呼び出された場合は管理者から呼び出された場合MyObjectゲストである

(MyObject)Activator.CreateInstance(type); 

。私は何が欠けていますか?もちろん、ジェネリックスを試しましたが、インターフェイスを実装するときには具体的な型が必要です。基本的にはすべての子孫クラスに実装する必要があります。

+0

このスキームを使用する場合は、既に指摘したように、うまくいきません。クラスの継承方法を変更する必要があります。あなたはそうは思わない?私は 'IUser'が公開メソッド' Login'を必要としていると思います –

+0

お問い合わせいただきありがとうございます。 これは私にとってだけではなく、他にもたくさんの方法があります。ここでは簡単にしたいと思っています。 私は 'IUser'で定義されたメソッドで' reflection'を使用します。実際の変数の型を返す 'Get()'と言います。ドバイ? – agiro

+1

私はすでにこれをいくつかのゲームで使っています。基本的に、 'Monster'クラスと' User'クラスは 'Unit'から派生しています。私は基本クラスでメソッド 'GetUnitType()'を定義しています。それもかなり速いです:) –

答えて

1

私たちがコメントで話した内容に基づいて、私たちのサーバーサイドのゲームコードから直接コピー貼り付けされたフォームがあります。しかし、覚えておいてください:IUserインターフェイスを定義しても、後で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; 
} 
+0

答えをありがとう。私がこれで作ることができないことは、これからどのようにインスタンス化するのでしょうか? 私はいくつかのコードで私の質問を更新しています、ちょっとしたことです... – agiro

+0

なぜあなたはこれをしますか?私はインスタンスに、それがどんな型であるかをさらに説明するメンバを持つべき理由を知りません。あなたは 'if(someUnit.UnitType == typeof(BattleMonster))'をしていますか?それをしないでください。代わりに 'if(someUnitはBattleMonsterです)'を実行してください。オブジェクトにはすでに実際のタイプがあります。 – poke

+0

@pokeはいまれに、if(someUnit.UnitType == typeof(BattleMonster)) 'を実行します。 'is'を使うのはほとんどありません。なぜなら、それはキャストを行い、たいていの場合、変数をキャストすることになります。 –

0

これは実際には可能で、それほど難しくありません。

SOLUTION 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」でパスワードを取得。

市長の欠点:

は私があるため、ダイナミックのインテリセンスを使用することができませんよ。

溶液2:USING拡張メソッド

この1つは実装し、使用するために、両方のビット醜いが、一方が依然としてインテリセンスの力を利用することができます。

は、そこでここでは、この細かい拡張メソッドを持っています。

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; 
} 

Tは私が後でasキーワードを使用していた場合、クラスである必要があります。

そして、私のゲストでGetの実装では、それが再びGetを実装するために子孫を必要としません。もちろん、

public T Get<T>() where T:class 
{ 
    var _instance = this; 
    return _instance as T; 
} 

のようなものです。

完了すると、私たちは現在の型を取得することができます

IUser adm = new Admin("wut", "mehpw", 1000); 
var stuff = adm.Get<Admin>().Name; 

欠点:

を私は基本的に、これはないより、私が使用しているオブジェクトの種類を知っている必要があります使用しているよりも

var stuff = (adm as Admin).Name; 

ここではエッジがほとんどありません。

私は基本的には指定されたプロパティ値を持つクラスをロードすると考えることができますが、それは私がIUserを作成し、確かに非常に遅いだろうと同じ参照ではありません。