0

Given this code:

public static class MainClass
{
    public static class SubClass
    {
        public const long poperty1 = 365635;

        public const long poperty2 = 156346;
        public const long poperty3 = 280847;
    }

    public static class SubClass2
    {
        public const long poperty4 = 36351526;

        public const long poperty6 = 152415;
        public const long poperty7 = 280114157;
    }
}

Is possible to add a method for the MainClass that with a IEnum and the name of a subclass returns true or false if the subClass contains one or more properties with that long?

E.g.

public static class MainClass {
...
    public static bool FindProperty(string subClassName, IEnumerable<long> list)
    {
         //code
    }

}
dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    It is possible using reflection, but it is messy and is not recommended for such use case. Did you try to use Dictionary for that? – Ghasan غسان Aug 31 '18 at 03:26
  • This feels like a XY problem - https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem . **Why** do you want to do this? – mjwills Aug 31 '18 at 04:24

3 Answers3

1

Actually you need to get TypeInfo using GetMembers method, by checking member type as nested type.

public static bool FindProperty(string className, IEnumerable<long> list)
{
    var allSubClass = typeof(MainClass)
                         .GetMembers()
                         .Where(m => m.MemberType == System.Reflection.MemberTypes.NestedType);        

    var classLookingFor = allSubClass.FirstOrDefault(c => string.Equals(c.Name, className, System.StringComparison.InvariantCultureIgnoreCase));

    if (classLookingFor == null)
    {
        Console.WriteLine("Class {0} not found.", className);
        return false;
    }
    else
    {
        // get all properties, in fact they are fields type of 'long/Int64'
        var allProp = (classLookingFor as TypeInfo).DeclaredFields.Where(f => f.FieldType == typeof(long));
        var anyPropWithValue = allProp.Any(p => list.Any(lng => lng == (long)p.GetValue(null)));
        return anyPropWithValue;            
    }
}

you can find the fiddle here. https://dotnetfiddle.net/d3dbYr

I guess its expected result -

var list = new List<long> { 36351526, 365635, 280847 };
MainClass.FindProperty("SubClass", list);    // it returns 'true', as SubClass contains 365635
MainClass.FindProperty("SubClass2", list);   // it returns 'true', as SubClass2 contains 36351526
MainClass.FindProperty("SubClass3", list);   // it returns 'false' as there is not such class

list = new List<long> { 99999999 };
MainClass.FindProperty("SubClass", list);    // it returns 'false' Sub class doesn't contain any property that has value as '99999999'

Update you can modify the code little more on need -

var members = typeof(MainClass).GetMember(className);

if (!members.Any())
{
    Console.WriteLine($"Class {className} not found.");
    return false;
}
else
{

    var allProp = (members[0] as TypeInfo).DeclaredFields.Where(f => f.FieldType == typeof(long));
    var anyPropWithValue = allProp.Any(p => list.Any(lng => lng == (long)p.GetValue(null)));
    return anyPropWithValue;            
}
Deepak Sharma
  • 4,124
  • 1
  • 14
  • 31
0

Using dictionaries like:

public static class MainClass
{
    public static Dictionary<string, Dictionary<string, long>> Dictionaries = new Dictionary<string, Dictionary<string, long>>() {
        { "SubDictionary", new Dictionary<string, long>()
            {
                { "property1", 365635},
                { "property2", 156346},
                { "property3", 280847},
            }
        },
        { "SubDictionary2", new Dictionary<string, long>()
            {
                { "property4", 36351526  },
                { "property5", 152415    },
                { "property6", 280114157 },
            }
        }
    };

    public static bool FindProperty(string subDictionaryName, IEnumerable<long> list)
    {
        Dictionary<string, long> dict;
        Dictionaries.TryGetValue(subDictionaryName, out dict);
        if (dict == null)
        {
            return false;
        }

        if (list.Any(i => dict.ContainsValue(i)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

Now you can use the function FindProperty as expected.

MainClass.FindProperty("SubDictionary", new List<long>() {365635 }); // True
Ghasan غسان
  • 5,577
  • 4
  • 33
  • 44
-1

We'll need to use reflection.

Here's my attempt.

public static void Main()
{
    Console.WriteLine(FindProperty("SubClass", new List<long>() { 156346 }));
    Console.WriteLine(FindProperty("SubClass", new List<long>() { 1 }));
    Console.WriteLine(FindProperty("SubClass2", new List<long>() { 280114157 }));

    //True
    //False
    //True
}


public static bool FindProperty<T>(string subClassName, IEnumerable<T> toFind)
{
    var consts = GetConsts<T>(subClassName);


    //The logic here may not be exactly what you need, 
    //but this is just an example
    return toFind.Any(x => consts.Contains(x));
}


static IEnumerable<T> GetConsts<T>(string subClassName)
{
    var allTypes = Assembly.GetExecutingAssembly().GetTypes();

    var myType = allTypes.FirstOrDefault(t => t.Name.EndsWith(subClassName));

    if (myType == null)
    {
        return Enumerable.Empty<T>();
    }

    var consts = GetConstants(myType);



    var first = consts.First();

    var constsOfTypeT = consts
        .Where(c => c.FieldType == typeof(T));

    return constsOfTypeT
        .Select(c => (T)c.GetRawConstantValue());
}


/// <summary>
/// From https://stackoverflow.com/questions/10261824/how-can-i-get-all-constants-of-a-type-by-reflection#10261848
/// by gdoron
/// </summary>
private static List<FieldInfo> GetConstants(Type type)
{
    FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
         BindingFlags.Static | BindingFlags.FlattenHierarchy);

    return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
}
tymtam
  • 31,798
  • 8
  • 86
  • 126