Мне нужно отфильтровать объекты контейнерной базы на интерфейсе, который они реализуют, одним из них является Ibase, это будет сделано для известных интерфейсов:
selObjs = container.Where(component => typeof(Ibase).IsAssignableFrom(component.GetType())).ToList();
Но я получаю имена интерфейсов из конфигурации Так как интерфейс не может быть создан, я не могу использовать переменную, присоединенную к GetType (), кроме того, использование переключателя нецелесообразно, поэтому я получаю тип интерфейса из сборки.
string interfaceName = "IbaseG<Type>";
interfaceName = $"{interfaceName .Substring(0, interfaceName.IndexOf("<"))}`1";
Type selInterf = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => String.Equals(t.Name, interfaceName, StringComparison.Ordinal)).ToArray()[0];
selObjs = Container.Where(component => selInterf.IsAssignableFrom(component.GetType())).ToList();
Он отлично работает для не * обобщенных c интерфейсов, но если интерфейс Generi c, интерфейс, полученный из сборки, имеет то же имя и GUID, что и typeof(IbaseG<Type>)
, но Тип и полное имя различаются, и оно не совпадает с использованием IsAssignableFrom.
Это небольшое консольное приложение, которое показывает различия между интерфейсами Generi c и Non-Generi c
namespace ConsoleApp {
using System;
using System.Collections.Generic;
using System.Linq;
public interface IbaseG<T> { T Val { get; } }
public class BaseG<T> : IbaseG<T> {
public T Val { get; }
public BaseG() { }
}
public class ExtG<T> : BaseG<T> {
public ExtG() { }
}
public interface Ibase { string Val { get; } }
public class Base : Ibase {
public string Val { get; }
public Base() { }
}
public class Ext : Base {
public Ext() { }
}
class Program {
static void Main(string[] args) {
Console.WriteLine("Begin Test");
bool isAssignable = typeof(IbaseG<string>)
.IsAssignableFrom(new ExtG<string>().GetType()); // true
// Non Generic Type
Test("Ibase", typeof(Ibase), new Ext());
// Generic Type
Test("IbaseG<string>", typeof(IbaseG<string>), new ExtG<string>());
Console.ReadLine();
}
static void Test(string interName, Type typeofType, object obj) {
if (typeofType.IsGenericType)
interName = $"{interName.Substring(0, interName.IndexOf("<"))}`1";
Type assmType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => String.Equals(t.Name, interName, StringComparison.Ordinal))
.ToArray()[0];
Dictionary<string, string> results = new Dictionary<string, string>();
results.Add($"assembly.GetType({assmType.Name})
.IsAssignableFrom({obj.GetType().Name}) 1",
(assmType.IsAssignableFrom(obj.GetType()).ToString()));
results.Add($"typeof({typeofType.Name})
.IsAssignableFrom({obj.GetType().Name}) 2",
(typeofType.IsAssignableFrom(obj.GetType()).ToString()));
results.Add("Same Type", (assmType == typeofType).ToString()); // true
results.Add("Same Name", (assmType.Name == typeofType.Name).ToString()); // true
results.Add("Same FullName", (assmType.FullName == typeofType.FullName).ToString()); // true
results.Add("Same GUID", (assmType.GUID == typeofType.GUID).ToString()); // true
if (assmType.IsGenericType)
Console.WriteLine($"Generic Type: {interName} Results");
else
Console.WriteLine($"Non Generic Type: {interName} Results");
foreach (KeyValuePair<string, string> result in results)
Console.WriteLine($"{result.Key}: {result.Value}");
Console.WriteLine($"typeof({typeofType.Name}).FullName: {typeofType.FullName}");
Console.WriteLine($"assembly.GetType({assmType.Name}).FullName: {assmType.FullName}");
Console.WriteLine($"typeof({typeofType.Name}).GUID: {typeofType.GUID}");
Console.WriteLine($"assembly.GetType({assmType.Name}).GUID: {assmType.GUID}");
Console.WriteLine();
}
}
}
Любая помощь будет принята с благодарностью.