Visų tipų, kurie diegia sąsają, gavimas

Naudodamasis refleksija, kaip galiu gauti visus tipus, kurie įdiegia sąsają su mažiausiu kodu C # 3.0 / .NET 3.5 ir sumažina iteracijas?

Štai ką noriu perrašyti:

 foreach (Type t in this.GetType().Assembly.GetTypes()) if (t is IMyInterface) ; //do stuff 
476
25 авг. nustatė juan 25 rug. 2008-08-25 22:57 '08 10:57 pm 2008-08-25 22:57
@ 13 atsakymų

Kasykloje bus C # 3.0 :)

 var type = typeof(IMyInterface); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => type.IsAssignableFrom(p)); 

Iš esmės mažiausias iteracijų skaičius visada bus:

 loop assemblies loop types see if implemented. 
694
25 авг. Atsakyti Darren Kopp 25 rug. 2008-08-25 23:11 '08 at 11:11 pm 2008-08-25 23:11

Jei norite rasti visus asortimento tipus, įgyvendinančius IFoo sąsają:

 var results = from type in someAssembly.GetTypes() where typeof(IFoo).IsAssignableFrom(type) select type; 

Atkreipkite dėmesį, kad Ryan Rinaldi pasiūlymas yra neteisingas. Jis grąžins 0 tipų. Jūs negalite rašyti

border=0
 where type is IFoo 

Kadangi tipas yra System.Type egzempliorius, jis niekada nebus IFoo tipo. Vietoj to, patikrinkite, ar galite priskirti tokio tipo IFoo. Tai suteiks jums tikėtinus rezultatus.

Be to, Adam Wright pasiūlymas, kuris šiuo metu pažymėtas kaip atsakymas, taip pat yra neteisingas dėl tos pačios priežasties. Veikimo metu pamatysite, kad grąžinami 0 tipai, nes visi System.Type atvejai nebuvo IFoo kūrėjai.

55
25 авг. Judo atsakymas Gabriel Himango 25 rug . 2008-08-25 23:20 '08, 23:20, 2008-08-25 23:20

Jis dirbo man. Ji suskirsto į klases ir patikrina, ar jie išgyvena iš „MyInterface“

  foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes() .Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) { //do stuff } 
53
26 сент. Ben Watkins atsakymas rugsėjo 26 d 2012-09-26 15:55 '12 at 15:55 2012-09-26 15:55

Suprantu, kad tai yra labai senas klausimas, bet aš maniau, kad ateityje norėčiau pridėti dar vieną atsakymą, nes visi šiandien pateikti atsakymai naudoja tam tikrą Assembly.GetTypes formą.

Nors „GetTypes“ () grąžina visus tipus, tai nebūtinai reiškia, kad galėtumėte juos suaktyvinti ir tokiu būdu galėtų mesti „ ReflectionTypeLoadException .

Klasikinis nesugebėjimo aktyvuoti tipą pavyzdys būtų, kai derived tipas yra derivedbase , bet base apibrėžta kitokiame komplekse, nei derived , surinkime, kuris skambina agregatui.

Sakykime:

 Class A // in AssemblyA Class B : Class A, IMyInterface // in AssemblyB Class C // in AssemblyC which references AssemblyB but not AssemblyA 

Jei ClassC , esančioje AssemblyC , mes darome kažką pagal priimtą atsakymą:

 var type = typeof(IMyInterface); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => type.IsAssignableFrom(p)); 

Tada jis išmeta „ ReflectionTypeLoadException .

Taip yra todėl, kad be AssemblyA AssemblyC nuorodos į AssemblyC jūs negalite:

 var bType = typeof(ClassB); var bClass = (ClassB)Activator.CreateInstance(bType); 

Kitaip tariant, ClassB neįkelia, ką gauna „GetTypes“ skambučiai ir meta.

Taigi, norint saugiai įkelti pakrovimo tipų rinkinį, pagal šį Phil Haacked straipsnį, norėdami gauti visus surinkimo tipus ir „Jon Skeet“ kodą , atliktumėte kažką panašaus:

 public static class TypeLoaderExtensions { public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) { if (assembly == null) throw new ArgumentNullException("assembly"); try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { return e.Types.Where(t => t != null); } } } 

Ir tada:

 private IEnumerable<Type> GetTypesWithInterface(Assembly asm) { var it = typeof (IMyInterface); return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList(); } 
46
01 апр. atsakymas suteiktas rismui 01 balandžio. 2015-04-01 01:41 '15 at 1:41 am 2015-04-01 01:41

Kiti atsakymai čia yra IsAssignableFrom . Taip pat galite naudoti „ FindInterfacesSystem vardų vietos, kaip aprašyta čia .

Čia pateikiamas pavyzdys, kuris tikrina visas sąrankas dabartiniame vykdomojo kūrimo aplanke ir ieško klasių, įgyvendinančių konkrečią sąsają (vengiant LINQ aiškumo).

 static void Main() { const string qualifiedInterfaceName = "Interfaces.IMyInterface"; var interfaceFilter = new TypeFilter(InterfaceFilter); var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var di = new DirectoryInfo(path); foreach (var file in di.GetFiles("*.dll")) { try { var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName); foreach (var type in nextAssembly.GetTypes()) { var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName); if (myInterfaces.Length > 0) { // This class implements the interface } } } catch (BadImageFormatException) { // Not a .net assembly - ignore } } } public static bool InterfaceFilter(Type typeObj, Object criteriaObj) { return typeObj.ToString() == criteriaObj.ToString(); } 

Jei norite sujungti kelis, galite pritaikyti sąsajų sąrašą.

19
08 июня '12 в 14:18 2012-06-08 14:18 atsakymas duodamas hillstuk birželio 08 d. 14:18 2012-06-08 14:18

pereikite per visas pakrautas sąrankas, eikite per visus jų tipus ir pažiūrėkite, ar jie įgyvendina sąsają.

kažkas panašaus:

 Type ti = typeof(IYourInterface); foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { foreach (Type t in asm.GetTypes()) { if (ti.IsAssignableFrom(t)) { // here your type in t } } } 
14
25 авг. Lasse Vågsæther Karlsen atsakymas rugpjūčio 25 d. 2008-08-25 23:05 '08, 11:05 val. 2008-08-25 23:05

Jis dirbo man (jei norite, kad galite pašalinti sistemos tipus paieškoje):

 Type lookupType = typeof (IMenuItem); IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where( t => lookupType.IsAssignableFrom(t)  !t.IsInterface); 
8
12 нояб. Carl Nayak atsakymas lapkričio 12 d 2010-11-12 17:30 '10, 17:30, 2010-11-12 17:30

Redaguoti: aš tik mačiau redagavimą, kad išsiaiškintumėte, jog pradinis klausimas buvo sumažinti iteracijas / kodą, o viskas yra gera ir gera, kaip ir mankšta, bet realiose situacijose jums reikia greičiausios, nesvarbu, kaip vėsioje LINQ.

Čia yra mano „Utils“ metodas pakartotinai perkelti į įkeltus tipus. Jis tvarko įprastas klases, taip pat sąsajas, o „izslēgti sistemos“ tipų parinktis žymiai pagreitina darbą, jei ieškote diegimų savo / trečiosios šalies kodų bazėje.

 public static List<Type> GetSubclassesOf(this Type type, bool excludeSystemTypes) { List<Type> list = new List<Type>(); IEnumerator enumerator = Thread.GetDomain().GetAssemblies().GetEnumerator(); while (enumerator.MoveNext()) { try { Type[] types = ((Assembly) enumerator.Current).GetTypes(); if (!excludeSystemTypes || (excludeSystemTypes  !((Assembly) enumerator.Current).FullName.StartsWith("System."))) { IEnumerator enumerator2 = types.GetEnumerator(); while (enumerator2.MoveNext()) { Type current = (Type) enumerator2.Current; if (type.IsInterface) { if (current.GetInterface(type.FullName) != null) { list.Add(current); } } else if (current.IsSubclassOf(type)) { list.Add(current); } } } } catch { } } return list; } 

Tai negraži, aš prisipažinu.

5
25 авг. atsakymas pateikiamas žodžiu2k 25 rug . 2008-08-25 23:12 '08 at 11:12 pm 2008-08-25 23:12

Kitas atsakymas neveikė su universalia sąsaja .

Taip, tiesiog pakeiskite tipo (ISomeInterface) tipą (T).

 List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()) .Where(x => typeof(ISomeInterface).IsAssignableFrom(x)  !x.IsInterface  !x.IsAbstract) .Select(x => x.Name).ToList(); 

Taigi su

 AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()) 

mes gauname visus statinius

 !x.IsInterface  !x.IsAbstract 

naudojama sąsajai ir abstrakčiai ir

 .Select(x => x.Name).ToList(); 

juos įtraukti į sąrašą.

4
19 сент. Antonino GAVREL atsakymas rugsėjo 19 d 2018-09-19 20:23 '18, 20:23, 2018-09-19, 20:23

Nėra paprasto būdo (vykdymo požiūriu) daryti tai, ką norite daryti.

Apmąstymai daugiausia susiję su asamblėjais ir tipais, todėl jums reikės surinkti visus surinkimo tipus ir pateikti užklausą dėl teisingos sąsajos. Štai pavyzdys:

 Assembly asm = Assembly.Load("MyAssembly"); Type[] types = asm.GetTypes(); Type[] result = types.where(x => x.GetInterface("IMyInterface") != null); 

Tai suteiks jums visus tipus, kurie įdiegia IMyInterface įrenginyje MyAssembly

2
25 авг. Jorge Córdoba atsakymas, pateiktas rugpjūčio 25 d. 2008-08-25 23:13 '08 at 23:13 pm 2008-08-25 23:13

Turiu išimčių linq kode, todėl aš tai darau (be sudėtingo pratęsimo):

 private static IList<Type> loadAllTypes(Types[] interfaces) { IList<Type> objects = new List<Type>(); // find all types foreach (var interfaceType in interfaces) foreach (var currentAsm in AppDomain.CurrentDomain.GetAssemblies()) try { foreach (var currentType in currentAsm.GetTypes()) if (interfaceType.IsAssignableFrom(currentType)  currentType.IsClass  !currentType.IsAbstract) objects.Add(currentType); } catch { } return objects; } 
0
27 февр. atsakymą pateikė vartotojo6537157 vasario 27 d. 2018-02-27 13:47 '18, 01:47 pm 2018-02-27 13:47

Dar geriau pasirenkant surinkimo vietą. Filtruokite daugumą agregatų, jei žinote, kad visos jūsų įdiegtos sąsajos yra toje pačioje asamblėjoje. Nustatyti tipai.

 // We get the assembly through the base class var baseAssembly = typeof(baseClass).GetTypeInfo().Assembly; // we filter the defined classes according to the interfaces they implement var typeList = baseAssembly.DefinedTypes.Where(type => type.ImplementedInterfaces.Any(inter => inter == typeof(IMyInterface))).ToList(); 

Kan Bilgin

0
21 янв. atsakymas, kurį pateikė user489566 Jan 21 2019-01-21 23:23 '19 , 11:23 PM 2019-01-21 23:23

Norėdami gauti sąrašą, galite naudoti LINQ:

 var types = from type in this.GetType().Assembly.GetTypes() where type is ISomeInterface select type; 

Bet ar tai tikrai lengviau skaitoma?

-3
25 авг. atsakymą pateikė Ryan Rinaldi 25 rug. 2008-08-25 23:18 '08 at 11:18 pm 2008-08-25 23:18

Kiti klausimai apie žymių arba Užduoti klausimą