开发者

In C#, how can you access a static property of a user-defined type without knowing the type at compiletime?

开发者 https://www.devze.com 2023-03-09 18:08 出处:网络
I have some classes that all implement a certain interface. I want to store a unique string in each class that I can get without creating an object for that class. I searched through a lot of posts he

I have some classes that all implement a certain interface. I want to store a unique string in each class that I can get without creating an object for that class. I searched through a lot of posts her开发者_高级运维e already and couldn't find an answer.

If I create an object for each class, then what I want is simply:

    class X:IBase{ string m = "x";}

    class Y:IBase{string m = "x";}

    class Z:IBase{string m = "x";}

    class interface IBase{ string m;}

    static int Main(){
      IBase[] arr = {new X(), new Y(), new Z()};
      foreach(IBase b in arr){
          Console.WriteLine(b.m);
      }
    }

But I want to do this without creating an object. So I want to do this:

    class X:IBase{ static string m = "x";}

    class Y:IBase{ static string m = "x";}

    class Z:IBase{ static string m = "x";}

    class interface IBase{ //no static fields allowed}

    static int Main(){
      Type[] arr = {X, Y, Z};
      foreach(Type t in arr){
          Console.WriteLine(t.m); //error, cannot resolve symbol m
      }
    }

Am I missing something obvious or is this just impossible?

The reason I don't want to create an object is because I want to display this string at the start, when I don't need any objects. I only create an object when I need to to save space.


The obvious thing here is to have m be an attribute of an abstract base class and assign a new value in the static constructors of your derivative classes.

You can also use System.Reflection for this, if you don't want to go the easy route (abstract base class).

You can also add Attributes to your classes and look up the values there.

Here is the easy route with abstract base classes:

abstract class AbstractBase: IBase { protected static string m = "?"; }

class X: AbstractBase { static X() { m = "x"; }}

class Y: AbstractBase { static Y() { m = "y"; }}

class Z: AbstractBase { static Z() { m = "z"; }}

interface IBase { //no static fields allowed}
}

static int Main(){
  AbstractBase[] arr = {new X(), new Y(), new Z()};
  foreach(AbstractBase t in arr){
      Console.WriteLine(t.m); // :)
  }
}

EDIT: I fixed the code sample to remove the compiler errors. Sorry for posting code that wasn't quite right. Doing so, I noticed that the foreach loop can't really be done without creating objects, since (unlike python) c# won't let you just refer to a type and call methods on it - that is the job of System.Reflection, so, as others have pointed out, you will want to check out GetMember and friends.


Reflection is your friend:

interface IBase { }
class X : IBase { static string m = "x";}    
class Y : IBase { static string m = "y";}    
class Z : IBase { static string m = "z";}

static void Main()
{
    Type[] arr = { typeof(X), typeof(Y), typeof(Z) };
    foreach (Type t in arr)
    {
        FieldInfo fieldInfo = t.GetField("m", 
                BindingFlags.Static | BindingFlags.NonPublic);
        Console.WriteLine(fieldInfo.GetValue(null));
    }
}

Note how Type[] arr = {X, Y, Z}; has been changed into Type[] arr = { typeof(X), typeof(Y), typeof(Z) }; in order to get the Type object for each of the types.


Type[] arr = new[] { typeof(X), typeof(Y), typeof(Z) };
foreach(Type t in arr)
{
    FieldInfo fi = t.GetField("m", BindingFlags.Static | BindingFlags.NonPublic);
    // or PropertyInfo pi = t.GetProperty(...);
    string m  = (string)fi.GetValue(null);
    // GetValue(null, null);
}


You need to use Reflection to access that property....

Like as below ( Example )

 MyTypeb = typeof(Myfieldb);
    FieldInfo Myfieldinfob = MyTypeb.GetField("field",BindingFlags.NonPublic|BindingFlags.Static);

Console.Write("{0}; ", Myfieldinfoa.GetValue(Myfielda));
0

精彩评论

暂无评论...
验证码 换一张
取 消