admin管理员组文章数量:1416631
I have the following interface which contains a static method definition:
public interface IUpgradableDataSource
{
static abstract Task<JsonElement> UpgradeSourceConfigurationAsync(
JsonElement configuration,
CancellationToken cancellationToken
);
}
This interface is implemented by dynamically loaded plugins. To invoke UpgradeSourceConfigurationAsync
on them, I need to use reflection which I would like to avoid (dataSourceType
is the plugin's type):
var dataSourceType = <the System.Type of the plugin>
var dataSourceInterfaceTypes = dataSourceType.GetInterfaces();
if (dataSourceInterfaceTypes.Any(x => x == typeof(IUpgradableDataSource)))
{
var methodInfo = dataSourceType
.GetMethod(
nameof(IUpgradableDataSource.UpgradeSourceConfigurationAsync),
BindingFlags.Public | BindingFlags.Static
)!;
var upgradedConfiguration = await (Task<JsonElement>)methodInfo.Invoke(
default,
[
configuration,
cancellationToken
]
)!;
// ...
}
else
{
// ...
}
I am implementing exactly the same code also in Python where I can solve this problem quite elegant:
if issubclass(data_source_type, IUpgradableDataSource):
upgraded_configuration = await data_source_type.upgrade_source_configuration(configuration)
...
else
...
By simply using issubclass
I get proper intellisense support and pyright is also happy:
My question is: Is there something similar in C#? I.e. can I just check if the System.Type
instance is deriving from IUpgradableDataSource
and then invoke static methods defined on that type?
I tried the following but it does not work (compile-time error):
var myCastedType = dataSourceType as IUpgradableDataSource;
await myCastedType.UpgradeSourceConfigurationAsync(...)
I have the following interface which contains a static method definition:
public interface IUpgradableDataSource
{
static abstract Task<JsonElement> UpgradeSourceConfigurationAsync(
JsonElement configuration,
CancellationToken cancellationToken
);
}
This interface is implemented by dynamically loaded plugins. To invoke UpgradeSourceConfigurationAsync
on them, I need to use reflection which I would like to avoid (dataSourceType
is the plugin's type):
var dataSourceType = <the System.Type of the plugin>
var dataSourceInterfaceTypes = dataSourceType.GetInterfaces();
if (dataSourceInterfaceTypes.Any(x => x == typeof(IUpgradableDataSource)))
{
var methodInfo = dataSourceType
.GetMethod(
nameof(IUpgradableDataSource.UpgradeSourceConfigurationAsync),
BindingFlags.Public | BindingFlags.Static
)!;
var upgradedConfiguration = await (Task<JsonElement>)methodInfo.Invoke(
default,
[
configuration,
cancellationToken
]
)!;
// ...
}
else
{
// ...
}
I am implementing exactly the same code also in Python where I can solve this problem quite elegant:
if issubclass(data_source_type, IUpgradableDataSource):
upgraded_configuration = await data_source_type.upgrade_source_configuration(configuration)
...
else
...
By simply using issubclass
I get proper intellisense support and pyright is also happy:
My question is: Is there something similar in C#? I.e. can I just check if the System.Type
instance is deriving from IUpgradableDataSource
and then invoke static methods defined on that type?
I tried the following but it does not work (compile-time error):
var myCastedType = dataSourceType as IUpgradableDataSource;
await myCastedType.UpgradeSourceConfigurationAsync(...)
Share
Improve this question
edited Feb 2 at 21:15
marc_s
757k184 gold badges1.4k silver badges1.5k bronze badges
asked Feb 2 at 20:59
Apollo3zehnApollo3zehn
5526 silver badges16 bronze badges
2
|
1 Answer
Reset to default 3You could have achieved this much more easily if you were working with instance methods:
if (dataSourceInstance is IUpgradableDataSource myCastedInstance){
await myCastedInstance.UpgradeSourceConfigurationAsync(...)
}
Static interface methods are meant to be called mostly in constrained methods like T.Method()
(see below).
As an aside, your implementation really excludes the possibility of implementing the interface method in the plugin with Explicit Interface Implementation:
public class Plugin : IUpgradableDataSource {
static Task<JsonElement> IUpgradableDataSource.UpgradeSourceConfigurationAsync(JsonElement configuration, CancellationToken cancellationToken) {
throw new NotImplementedException();
}
}
The method above would not be discovered with your reflection logic.
To work around this issue and make matters simpler, it would be very useful to define a helper method with the constraint T : IUpgradableDataSource
somewhere:
public static Task<JsonElement> UpgradeSourceConfigurationAsyncHelper<T>(
JsonElement configuration,
CancellationToken cancellationToken
)
where T : IUpgradableDataSource => T.UpgradeSourceConfigurationAsync(configuration, cancellationToken);
We would use this method as a template to construct delegates so we can invoke each plugin's implementation from reflection:
var dataSourceType = pluginType;
// TODO: make static field
var helperGenericMethod = typeof(ClassWithHelperMethod).GetMethod("UpgradeSourceConfigurationAsyncHelper");
if (dataSourceType.GetInterfaces().Any(x => x == typeof(IUpgradableDataSource))
/* alternatively dataSourceType.IsAssignableTo(typeof(IUpgradableDataSource))*/) {
// TODO:
// possibly cache in Dictionary<Type, Func<JsonElement, CancellationToken, Task<JsonElement>>>
var del = helperGenericMethod
.MakeGenericMethod(dataSourceType)
.CreateDelegate<Func<JsonElement, CancellationToken, Task<JsonElement>>>();
var upgradedConfiguration = await del(configuration,cancellationToken);
}
本文标签:
版权声明:本文标题:c# - Is there a language feature like Python's `issubclass` to cast instances of System.Type to the actual type (to acce 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745256500a2650134.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
as
to work with it. You should work with concrete instance, not an instance of theSystem.Type
. Without seeing full code it is hard to tell what you need to do, but in some cases you can useActivator.CreateInstance
:var castedInstance = Activator.CreateInstance(dataSourceType) as IUpgradableDataSource; if(castedInstance is not null) ...
– Guru Stron Commented Feb 2 at 21:22