0

I have the following architecture:

public interface IStatus
{
    string StatusName {get;}
}
public class A: IStatus
{
    public string StatusName {get {return "A Status";}}
}

public class B: IStatus
{
    public string StatusName {get {return "B Status";}}
}

public class C: IStatus
{
    public string StatusName {get {return "C Status";}}
}

I tried the following and I can see in debug all the relevant classes but I am not sure how to get the StatusName property for each one of the classes. I presume, I need to create an instance of each class somehow and ask for the StatusName property.

public class Test
{
    var type = typeof(IStatus);
    var types = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .Where(p => type.IsAssignableFrom(p));

        foreach (Type mytype in types)
        {
            var i = mytype.GetMember("StatusName");
            if (i.Count()!=0)
            {
                var n = i.GetValue(0);
            }               
        }
}

The expected result I need is a list of string with values: "A Status", "B Status", "C Status"

ehh
  • 3,412
  • 7
  • 43
  • 91
  • 1
    those strings are *instance* properties; so to get them you'd need an instance of each; do you have any instances? or should the properties be static? note: static members can't be in interfaces, and at that point maybe an "attribute" against the type is a better option, i.e. `[Status("A Status")] public class A { ... } ... [Status("B Status")] public class B { ... }` – Marc Gravell Mar 15 '18 at 14:49
  • Do you mean adding an attribute to those properties and find them using relection? – ehh Mar 15 '18 at 14:50
  • no, I meant adding an attribute to the *type*, but: only you know whether this value is "per type" or "per instance" – Marc Gravell Mar 15 '18 at 14:51
  • It definitely can be per type. An example or link may be very helpful – ehh Mar 15 '18 at 14:52
  • and is it *fixed* per type, or does it change at runtime based on what is happening? (because if so: then it shouldn't be an attribute). What *should* happen if you have 5 instances of B? do they share a status? do they have a status each? – Marc Gravell Mar 15 '18 at 14:54
  • It doesn't change, it is fixed – ehh Mar 15 '18 at 14:54
  • @Servy for the record, I don't think that's a good "duplicate" - this seems like an X/Y problem to me, and you've *broadly* linked to an X-dot-something (without explaining what you'd do with the instance), when IMO the problem/solution is actually Y-related – Marc Gravell Mar 15 '18 at 15:00
  • @MarcGravell It's answering the question actually asked, for anyone who actually needs to solve this problem, and you've pointed out that the OP what the OP should actually be doing instead of trying to even find the answer to this question, so it seems like the best of both words. Any future readers who have this actual problem see the solution, and the OP gets the solution that they should actually be using, even though it's unrelated to their actual question. – Servy Mar 15 '18 at 15:04
  • Servy, as you can see in my question, there are 2 phases to solve this issue: the first is to get all the classes and the second, as I presume, was to get to the property value itself from the class and as I thought it requires creating an instance of the class. A little messy. And here comes @MarcGravell with the right questions and found a very appropriate solution to me. So it is a win-win state, I get a better solution and I learn something new. – ehh Mar 15 '18 at 15:11

2 Answers2

1

Based on the comments it sounds like the statuses are per type and unchanging, and may be required independently of any instances. This makes them a poor choice for interfaces and a good fit for "attributes":

using System;
using System.Linq;

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
sealed class StatusAttribute : Attribute
{
    public StatusAttribute(string name) { Name = name; }
    public string Name { get; }
}
[Status("A Status")]
public class A
{ /* ... */  }

[Status("B Status")]
public class B
{ /* ... */  }

[Status("C Status")]
public class C
{ /* ... */  }

static class P
{
    static void Main()
    {
        var attrib = typeof(StatusAttribute);
        var pairs = from s in AppDomain.CurrentDomain.GetAssemblies()
                    from p in s.GetTypes()
                    where p.IsDefined(attrib, false)
                    select new
                    {
                        Type = p,
                        Status = ((StatusAttribute)Attribute.GetCustomAttribute(
                                  p, attrib)).Name
                    };

        foreach(var pair in pairs)
        {
            Console.WriteLine($"{pair.Type.Name}: {pair.Status}");
        }
    }

}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

You can create default instance for each of your types and then get value of each property, since they just have return "C Status", that should not be a problem

        var instance = Activator.CreateInstance(myType);
        var value = instance.GetType().GetProperty("StatusName").GetValue(instance);
Vidmantas Blazevicius
  • 4,652
  • 2
  • 11
  • 30