C
C#2y ago
memw

❔ Reflections and generics

So i have a type instance list and i'm iterating trough all the fields that the propertyType.Name.Contains("ExtensionConfig"), that type has a method which i need to invoke foreach field and i'm iterating trough the fields So basically the problem comes when i do (field as PropertyInfo).GetValue(type) shows invalid cast exception, and i can't cast because the target type has a generic type which in every field is different
52 Replies
memw
memwOP2y ago
foreach (Type type in Assembly.GetAssembly(typeof(Extension)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(Extension))))
{
ExtensionInstances.Add((Extension)System.Activator.CreateInstance(type, null));
foreach (PropertyInfo field in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{


//info.Invoke(field.GetValue(type), new object[] { type.Name });
}
}
ExtensionInstances.Sort();
foreach (Type type in Assembly.GetAssembly(typeof(Extension)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(Extension))))
{
ExtensionInstances.Add((Extension)System.Activator.CreateInstance(type, null));
foreach (PropertyInfo field in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{


//info.Invoke(field.GetValue(type), new object[] { type.Name });
}
}
ExtensionInstances.Sort();
in the foreach inside i'm iterating trough all the fields but i can't get it's value nor invoke any method inside
TheRanger
TheRanger2y ago
field is a FieldInfo, not a PropertyInfo
memw
memwOP2y ago
TheRanger
TheRanger2y ago
GetProperties() returns properties not fields try GetFields instead are u trying to return fields or properties? can u show ur class that ur trying to fetch fields or properties from?
memw
memwOP2y ago
so basically it's like this
public class SendSteamId : Extension
{
private DiscordWebhook _webhook = null!;

public ExtensionConfig<string> URL => new("url", "https://discord.com/api/webhooks/1052150142393913364/u6XndhiV-ovZx99iZxC4savuDAklOQ7PVXNd5Im6vEbs4oxym5p1CNSBkYGP_fCXBy18", "Where the embed will be sent");
public ExtensionConfig<bool> Enabled => new("toggle", true, "Whether to enable or disable the plugin");
public ExtensionConfig<string> Key => new("key", "p", "What keybind should the plugin use to send the embed");
public ExtensionConfig<Method> MessageMethod => new("method", Method.OnRoundStart, "Should the plugin send the embed on round start or on keybind press?");

public override void Start(){}
public override void Update(){}
}
public class SendSteamId : Extension
{
private DiscordWebhook _webhook = null!;

public ExtensionConfig<string> URL => new("url", "https://discord.com/api/webhooks/1052150142393913364/u6XndhiV-ovZx99iZxC4savuDAklOQ7PVXNd5Im6vEbs4oxym5p1CNSBkYGP_fCXBy18", "Where the embed will be sent");
public ExtensionConfig<bool> Enabled => new("toggle", true, "Whether to enable or disable the plugin");
public ExtensionConfig<string> Key => new("key", "p", "What keybind should the plugin use to send the embed");
public ExtensionConfig<Method> MessageMethod => new("method", Method.OnRoundStart, "Should the plugin send the embed on round start or on keybind press?");

public override void Start(){}
public override void Update(){}
}
this is the class i'm trying to get the fields
TheRanger
TheRanger2y ago
ok thats a property those arent fields
memw
memwOP2y ago
yeah that is what i was getting get properties and so i need to access it's value, and it's value contains a method that is InitConfig
public class ExtensionConfig<T>
{
private readonly string _settingName;
private readonly T _defaultValue;
private readonly string _description;

public T Value { get; protected set; } = default!;

public ExtensionConfig(string settingName, T defaultValue, string description)
{
_settingName = settingName;
_defaultValue = defaultValue;
_description = description;
}

public void InitConfig(string methodName)
{
Instance.Log.LogInfo(methodName);
Value = StaticConfig.Bind(methodName, _settingName, _defaultValue, _description).Value;
}
}
public class ExtensionConfig<T>
{
private readonly string _settingName;
private readonly T _defaultValue;
private readonly string _description;

public T Value { get; protected set; } = default!;

public ExtensionConfig(string settingName, T defaultValue, string description)
{
_settingName = settingName;
_defaultValue = defaultValue;
_description = description;
}

public void InitConfig(string methodName)
{
Instance.Log.LogInfo(methodName);
Value = StaticConfig.Bind(methodName, _settingName, _defaultValue, _description).Value;
}
}
this is the type and i need to run InitConfig basically but i always get that invalid cast exception
TheRanger
TheRanger2y ago
so can u show the image where its throwing invalid cast exception ?
memw
memwOP2y ago
sure
TheRanger
TheRanger2y ago
brb
memw
memwOP2y ago
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Specified cast is not valid.
at (wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
at System.Reflection.RuntimePropertyInfo.GetterAdapterFrame[T,R] (System.Reflection.RuntimePropertyInfo+Getter`2[T,R] getter, System.Object obj) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x0006c] in <986ed57b9a8f4699a3c59a69eb05944a>:0
--- End of inner exception stack trace ---
at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x00080] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.PropertyInfo.GetValue (System.Object obj) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at CrabGameUtils.Plugin.Load () [0x000e0] in <36fe78a30a03475bb7e6152333288d25>:0
at BepInEx.IL2CPP.IL2CPPChainloader.LoadPlugin (BepInEx.PluginInfo pluginInfo, System.Reflection.Assembly pluginAssembly) [0x00011] in <e9997477cd8143c9a348224def0a337e>:0
at BepInEx.Bootstrap.BaseChainloader`1[TPlugin].LoadPlugins (System.Collections.Generic.IList`1[T] plugins) [0x0025c] in <16694cdb03bf4887828a298c286d045b>:0
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Specified cast is not valid.
at (wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
at System.Reflection.RuntimePropertyInfo.GetterAdapterFrame[T,R] (System.Reflection.RuntimePropertyInfo+Getter`2[T,R] getter, System.Object obj) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x0006c] in <986ed57b9a8f4699a3c59a69eb05944a>:0
--- End of inner exception stack trace ---
at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x00080] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.PropertyInfo.GetValue (System.Object obj) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at CrabGameUtils.Plugin.Load () [0x000e0] in <36fe78a30a03475bb7e6152333288d25>:0
at BepInEx.IL2CPP.IL2CPPChainloader.LoadPlugin (BepInEx.PluginInfo pluginInfo, System.Reflection.Assembly pluginAssembly) [0x00011] in <e9997477cd8143c9a348224def0a337e>:0
at BepInEx.Bootstrap.BaseChainloader`1[TPlugin].LoadPlugins (System.Collections.Generic.IList`1[T] plugins) [0x0025c] in <16694cdb03bf4887828a298c286d045b>:0
this is bascially the error i get i should mention this is BepInEx that happens when i call field.GetValue(type)
TheRanger
TheRanger2y ago
call it property not field, to avoid confustion
memw
memwOP2y ago
ok
memw
memwOP2y ago
TheRanger
TheRanger2y ago
so this Log.LogInfo line is throwing the error?
memw
memwOP2y ago
ye whenever i invoke GetValue(type)
TheRanger
TheRanger2y ago
GetValue expects an instance, not a type
memw
memwOP2y ago
oh. you are right i don't need to iterate the types but the instances damn
TheRanger
TheRanger2y ago
no
memw
memwOP2y ago
i store the instances in a list
TheRanger
TheRanger2y ago
you need to iterate the types to get the properties
vdvman1
vdvman12y ago
They probably want to iterate the instances, and call GetType() on each instance to get the type
TheRanger
TheRanger2y ago
but you need to know which instance to get the value of specified property
memw
memwOP2y ago
i have an idea
foreach (Type type in Assembly.GetAssembly(typeof(Extension)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(Extension))))
{
Extension instance = (Extension)System.Activator.CreateInstance(type, null);
ExtensionInstances.Add(instance);
foreach (PropertyInfo property in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{
Log.LogInfo(property.GetValue(instance));
//info.Invoke(field.GetValue(type), new object[] { type.Name });
}
}

foreach (Type type in Assembly.GetAssembly(typeof(Extension)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(Extension))))
{
Extension instance = (Extension)System.Activator.CreateInstance(type, null);
ExtensionInstances.Add(instance);
foreach (PropertyInfo property in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{
Log.LogInfo(property.GetValue(instance));
//info.Invoke(field.GetValue(type), new object[] { type.Name });
}
}

this should work
TheRanger
TheRanger2y ago
well if those properties are static, u dont need to pass an instance as an argument, just a null
vdvman1
vdvman12y ago
That assumes it's ok to create an instance and then discard it And in that case you could potentially use static fields/properties instead of instance fields/properties
memw
memwOP2y ago
they aren't static
TheRanger
TheRanger2y ago
i know but im saying if they are
memw
memwOP2y ago
it adds it to a static list i only need to run this one time
vdvman1
vdvman12y ago
Oh right, I missed that bit
memw
memwOP2y ago
Extension instance = (Extension)System.Activator.CreateInstance(type, null);
ExtensionInstances.Add(instance);
foreach (PropertyInfo property in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{
Log.LogInfo(property.GetValue(instance).GetType().GetMethod("InitValue")!.Invoke(instance, new object[]{type.Name}));
}
Extension instance = (Extension)System.Activator.CreateInstance(type, null);
ExtensionInstances.Add(instance);
foreach (PropertyInfo property in type.GetProperties().Where(p => p.PropertyType.Name.Contains("ExtensionConfig")))
{
Log.LogInfo(property.GetValue(instance).GetType().GetMethod("InitValue")!.Invoke(instance, new object[]{type.Name}));
}
this should be able to invoke the InitValue method from the instance if i'm not wrong
TheRanger
TheRanger2y ago
try and see
memw
memwOP2y ago
sounds like method is null
memw
memwOP2y ago
imma see what methods there are maybe i'm looking on the wrong place
TheRanger
TheRanger2y ago
GetMethod gets public methods by default otherwise you need to pass BindingFlags argument
memw
memwOP2y ago
the method is public and non static
TheRanger
TheRanger2y ago
ok
memw
memwOP2y ago
public void InitConfig(string methodName)
{
Instance.Log.LogInfo(methodName);
Value = StaticConfig.Bind(methodName, _settingName, _defaultValue, _description).Value;
}
public void InitConfig(string methodName)
{
Instance.Log.LogInfo(methodName);
Value = StaticConfig.Bind(methodName, _settingName, _defaultValue, _description).Value;
}
TheRanger
TheRanger2y ago
yeah you typod its InitConfig not InitValue
memw
memwOP2y ago
oops Object does not match target type
TheRanger
TheRanger2y ago
show image, and brb
memw
memwOP2y ago
[Error : BepInEx] Error loading [CrabGameUtils 1.0.0]: System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00024] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at CrabGameUtils.Plugin.Load () [0x00103] in <3223e68ea61a4b20a5289787755ee603>:0
at BepInEx.IL2CPP.IL2CPPChainloader.LoadPlugin (BepInEx.PluginInfo pluginInfo, System.Reflection.Assembly pluginAssembly) [0x00011] in <e9997477cd8143c9a348224def0a337e>:0
at BepInEx.Bootstrap.BaseChainloader`1[TPlugin].LoadPlugins (System.Collections.Generic.IList`1[T] plugins) [0x0025c] in <16694cdb03bf4887828a298c286d045b>:0
[Error : BepInEx] Error loading [CrabGameUtils 1.0.0]: System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00024] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] in <986ed57b9a8f4699a3c59a69eb05944a>:0
at CrabGameUtils.Plugin.Load () [0x00103] in <3223e68ea61a4b20a5289787755ee603>:0
at BepInEx.IL2CPP.IL2CPPChainloader.LoadPlugin (BepInEx.PluginInfo pluginInfo, System.Reflection.Assembly pluginAssembly) [0x00011] in <e9997477cd8143c9a348224def0a337e>:0
at BepInEx.Bootstrap.BaseChainloader`1[TPlugin].LoadPlugins (System.Collections.Generic.IList`1[T] plugins) [0x0025c] in <16694cdb03bf4887828a298c286d045b>:0
this is all it gives a runtime error oh i see it works now thanks
TheRanger
TheRanger2y ago
well yes when the exception gets thrown, you can see in the debugger what type is being invoked
memw
memwOP2y ago
nop, i can't see because i can't debug like that this is a class library that gets ran by an injector but it kinda works now i just have a dilema which is kinda weird if imma say so myself
TheRanger
TheRanger2y ago
well use Console.WriteLine to debug what are u trying to inject anyway?
memw
memwOP2y ago
it's a mod for crabgame injected trough bepinex as all the methods and stuff are obfuscated because the references are from il2cpp... i'm kinda making something to make this easier
TheRanger
TheRanger2y ago
what? does the game allow you to mod it?
memw
memwOP2y ago
well no bepinex just searches the program memory or something
TheRanger
TheRanger2y ago
that can get you banned from this server tho
memw
memwOP2y ago
that are not hacks it's nothing harmful at all and also the game creator says he doesn't care meanwhile it's not harmful, well said once he just didn't implement a way to mod the game cuz it doesn't get updated since 2 years ago and people seeking ways to make it a better experience
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server