2010-09-26 1 views
1

Должно быть легко ...Как проверить, является ли тип IEnumerable <BaseType>?

class Base{}  
class Foo:Base{} 

public bool Bar(Type t){ 
    // return ??? 
    // NB: shouldn't know anything about Foo, just Base 
} 

Assert.True(Bar(typeof(IEnumerable<Foo>)); 
Assert.False(Bar(typeof(IEnumerable<Base>)); 
Assert.False(Bar(typeof(string)); 
Assert.False(Bar(typeof(Foo)); 

Просто, чтобы ответить на вопрос, почему второй один должен быть ложным (на самом деле - это не имеет значения, вызвать Bar аргумент никогда не будет IEnumerable<Base>).

Я пытаюсь написать соглашение об автоопределении FluentNhibernate, которое сопоставляет мои перечисления классов целым числам. Я успешно сделал это уже, но все пошло вниз, когда я хотел отобразить IEnumerable<EnumerationChild> (в моем случае - User.Roles).

public class EnumerationConvention:IUserTypeConvention{ 
    private static readonly Type OpenType=typeof(EnumerationType<>); 
    public void Apply(IPropertyInstance instance){ 
     //this is borked atm, must implement ienumerable case 
     var closedType=OpenType.MakeGenericType(instance.Property.PropertyType); 
     instance.CustomType(closedType); 
    } 
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria){ 
     criteria.Expect(
     x=>typeof(Enumeration).IsAssignableFrom(x.Property.PropertyType) || 
      typeof(IEnumerable<Enumeration>) 
      .IsAssignableFrom(x.Property.PropertyType)); 
    } 
    } 
+0

Можете ли вы действительно не придумать лучшего имени для функции, чем «Бар»? – Timwi

+0

@ Тимви, что насчет 'Баз'? –

+0

@Arnis: Сколько фрагментов кода вы видели, у которых есть такие имена функций? Можете ли вы честно не думать о имени, которое * описывает функцию *? – Timwi

ответ

3

Вы можете использовать Type.IsAssignableFrom(Type). Тем не менее, ваш вопрос не совсем ясен - вы указываете один, но вам нужны два ... какой тип Bar предназначен для проверки t?

Обратите внимание, что ответ будет переключаться между .NET 3.5 и .NET 4, из-за общей ковариации - в .NET 3.5, например, List<Foo> является не присваиваемые IEnumerable<Base>, но в .NET 4 это.

EDIT: Вот программа, которая печатает True, True, False, False. Я не уверен, почему вы ожидали, что второй будет ложным:

using System; 
using System.Collections; 
using System.Collections.Generic; 

class Base{}  
class Foo:Base{} 

class Test 
{ 
    static bool Bar(Type t) 
    { 
     return typeof(IEnumerable<Base>).IsAssignableFrom(t); 
    } 

    static void Main() 
    { 
     Console.WriteLine(Bar(typeof(IEnumerable<Foo>))); 
     Console.WriteLine(Bar(typeof(IEnumerable<Base>))); 
     Console.WriteLine(Bar(typeof(string))); 
     Console.WriteLine(Bar(typeof(Foo))); 
    } 
} 
+0

Это будет работать, если аргумент 'typeof (Foo)'. Но, насколько я знаю, это не будет, если аргумент «typeof (IEnumerable )». –

+0

@Arnis: см. Мое редактирование. Вы используете .NET 3.5 или .NET 4? Также обратите внимание на мое редактирование, где я спрашиваю, какие * два * типа вы проверяете. Вы не указали, какой тип следует проверять в отношении 'IEnumerable '. –

+0

Использование C# 4 здесь. Тэгированный вопрос. –