En kolay yolu türlerinin bir koleksiyondan aynı temel sınıfa almak

oy
3

Bir koleksiyondaki öğelerinin özelliklerini görüntüleyen özel özellik ızgara inşa ediyorum. Ne yapmak istediğiniz her öğenin arasında yaygın olan ızgara sadece özelliklerini göstermek olduğunu. Ben koleksiyonunda her tür aynı temel sınıfa bulup özelliklerini bulunuyor göstermek olurdu bunu yapmanın en iyi yolu varsayıyorum. daha kolay bir yolu var mı? Bana Bunu yapmanın en iyi yaklaşımın bir kod örnek verebilir misiniz?

Oluştur 09/12/2008 saat 17:44
kaynak kullanıcı
Diğer dillerde...                            


6 cevaplar

oy
3

Ortak temel sınıfları için kontrol tutan bir yöntemle bunu yapabilirsiniz. Ben Tip sınıfının AnaSınıf özelliğini kullanarak, hızlı bir şekilde, bu kadar yazdım. Bir dizi bir listesini kullanmak zorunda değilsiniz ya da diğer IEnumerable bu küçük değişikliklerle birlikte çalışabilir.

Bunu test:

static void Main(string[] args)
{
    Console.WriteLine("Common Types: " + GetCommonBaseClass(new Type[] {typeof(OleDbCommand), typeof(OdbcCommand), typeof(SqlCommand)}).ToString());   
}

Ve DbCommand sağ cevabı var. İşte benim koddur.

    static Type GetCommonBaseClass(Type[] types)
    {
        if (types.Length == 0)
            return (typeof(object));
        else if (types.Length == 1)
            return (types[0]);

        // Copy the parameter so we can substitute base class types in the array without messing up the caller
        Type[] temp = new Type[types.Length];

        for (int i = 0; i < types.Length; i++)
        {
            temp[i] = types[i];
        }

        bool checkPass = false;

        Type tested = null;

        while (!checkPass)
        {
            tested = temp[0];

            checkPass = true;

            for (int i = 1; i < temp.Length; i++)
            {
                if (tested.Equals(temp[i]))
                    continue;
                else
                {
                    // If the tested common basetype (current) is the indexed type's base type
                    // then we can continue with the test by making the indexed type to be its base type
                    if (tested.Equals(temp[i].BaseType))
                    {
                        temp[i] = temp[i].BaseType;
                        continue;
                    }
                    // If the tested type is the indexed type's base type, then we need to change all indexed types
                    // before the current type (which are all identical) to be that base type and restart this loop
                    else if (tested.BaseType.Equals(temp[i]))
                    {
                        for (int j = 0; j <= i - 1; j++)
                        {
                            temp[j] = temp[j].BaseType;
                        }

                        checkPass = false;
                        break;
                    }
                    // The indexed type and the tested type are not related
                    // So make everything from index 0 up to and including the current indexed type to be their base type
                    // because the common base type must be further back
                    else
                    {
                        for (int j = 0; j <= i; j++)
                        {
                            temp[j] = temp[j].BaseType;
                        }

                        checkPass = false;
                        break;
                    }
                }
            }

            // If execution has reached here and checkPass is true, we have found our common base type, 
            // if checkPass is false, the process starts over with the modified types
        }

        // There's always at least object
        return tested;
    }
Cevap 09/12/2008 saat 18:13
kaynak kullanıcı

oy
2

tiplerinin kümesi için en özel ortak tabanını almak için yayınlanan kod bazı sorunlar vardır. I türlerinden biri olarak typeof (nesneyi) geçmesi Özellikle, kırılır. Ben şu basit ve (daha iyi) doğru olduğunu düşünüyoruz.

public static Type GetCommonBaseClass (params Type[] types)
{
    if (types.Length == 0)
        return typeof(object);

    Type ret = types[0];

    for (int i = 1; i < types.Length; ++i)
    {
        if (types[i].IsAssignableFrom(ret))
            ret = types[i];
        else
        {
            // This will always terminate when ret == typeof(object)
            while (!ret.IsAssignableFrom(types[i]))
                ret = ret.BaseType;
        }
    }

    return ret;
}

Ben de test:

Type t = GetCommonBaseClass(typeof(OleDbCommand),
                            typeof(OdbcCommand),
                            typeof(SqlCommand));

Ve var typeof(DbCommand). Ve birlikte:

Type t = GetCommonBaseClass(typeof(OleDbCommand),
                            typeof(OdbcCommand),
                            typeof(SqlCommand),
                            typeof(Component));

Ve var typeof(Compoment). Ve birlikte:

Type t = GetCommonBaseClass(typeof(OleDbCommand),
                            typeof(OdbcCommand),
                            typeof(SqlCommand),
                            typeof(Component),
                            typeof(Component).BaseType);

Ve var typeof(MarshalByRefObject). Ve birlikte

Type t = GetCommonBaseClass(typeof(OleDbCommand),
                            typeof(OdbcCommand),
                            typeof(SqlCommand),
                            typeof(Component),
                            typeof(Component).BaseType,
                            typeof(int));

Ve var typeof(object).

Cevap 31/03/2009 saat 17:26
kaynak kullanıcı

oy
2

Nesnelerin koleksiyonundan ortak özelliklerini almak için böyle bir yöntemi kullanabilirsiniz:

public static String[] GetCommonPropertiesByName(Object[] objs)
{
    List<Type> typeList = new List<Type>(Type.GetTypeArray(objs));
    List<String> propertyList = new List<String>();
    List<String> individualPropertyList = new List<String>();

    foreach (Type type in typeList)
    {
        foreach (PropertyInfo property in type.GetProperties())
        {
            propertyList.Add(property.Name);
        }
    }

    propertyList = propertyList.Distinct().ToList();

    foreach (Type type in typeList)
    {
        individualPropertyList.Clear();

        foreach (PropertyInfo property in type.GetProperties())
        {
            individualPropertyList.Add(property.Name);
        }

        propertyList = propertyList.Intersect(individualPropertyList).ToList();
    }

    return propertyList.ToArray();
}

Eğer bir şeyler yapmak isteyen bir mülkün dizesi yerleştirdikten sonra da, onun dize İsme Göre o Mülkiyet çağırmak için toplama ve kullanma yansımada Nesnelerin herhangi alabilir.

PropertyInfo p = t.GetType().GetProperty("some Property String Name");
p.GetValue(t, null);
p.SetValue(t, someNewValue, null);

Benzer şekilde, kod GetCommonPropertiesByNameyöntemiyle ortak üye, vb yöntemler, iç içe türleri, alanlar, almak için değiştirilebilir ...

Cevap 09/12/2008 saat 19:27
kaynak kullanıcı

oy
0

Böyle bir şey kullanmak ama Tony'nin cevabı muhtemelen daha iyidir:

internal class BaseFinder
{
    public static Type FindBase(params Type[] types)
    {
        if (types == null)
            return null;

        if (types.Length == 0)
            return null;

        Dictionary<Type, IList<Type>> baseTypeMap = new Dictionary<Type,IList<Type>>();

        // get all the base types and note the one with the longest base tree
        int maxBaseCount = 0;
        Type typeWithLongestBaseTree = null;
        foreach (Type type in types)
        {
            IList<Type> baseTypes = GetBaseTree(type);
            if (baseTypes.Count > maxBaseCount)
            {
                typeWithLongestBaseTree = type;
                maxBaseCount = baseTypes.Count;
            }
            baseTypeMap.Add(type, baseTypes);
        }

        // walk down the tree until we get to a common base type
        IList<Type> longestBaseTree = baseTypeMap[typeWithLongestBaseTree];
        for (int baseIndex = 0; baseIndex < longestBaseTree.Count;baseIndex++)
        {
            int commonBaseCount = 0;
            foreach (Type type in types)
            {
                IList<Type> baseTypes = baseTypeMap[type];
                if (!baseTypes.Contains(longestBaseTree[baseIndex]))
                    break;
                commonBaseCount++;
            }
            if (commonBaseCount == types.Length)
                return longestBaseTree[baseIndex];
        }
        return null;
    }

    private static IList<Type> GetBaseTree(Type type)
    {
        List<Type> result = new List<Type>();
        Type baseType = type.BaseType;
        do
        {
            result.Add(baseType);
            baseType = baseType.BaseType;
        } while (baseType != typeof(object));
        return result;
    }
}
Cevap 10/12/2008 saat 12:50
kaynak kullanıcı

oy
0

İşte türleri listesinden özelliklerinin ortak setini almak için bir yoldur:

class TypeHandler
{
    public static List<string> GetCommonProperties(Type[] types)
    {
        Dictionary<string, int> propertyCounts = new Dictionary<string, int>();

        foreach (Type type in types)
        {
            foreach (PropertyInfo info in type.GetProperties())
            {
                string name = info.Name;
                if (!propertyCounts.ContainsKey(name)) propertyCounts.Add(name, 0);
                propertyCounts[name]++;
            }
        }

        List<string> propertyNames = new List<string>();

        foreach (string name in propertyCounts.Keys)
        {
            if (propertyCounts[name] == types.Length) propertyNames.Add(name);
        }

        return propertyNames;
    }
}

Bu, tüm tiplerinde tüm özellikleri üzerinde dolaşır ve sadece türlerinin sayısına eşit bir kaç kez meydana gelen olanlarla biter.

Eğer kompakt LINQ sorguları tercih ediyorsanız aşağıdaki eşdeğer ifadeyi kullanabilirsiniz:

return (from t in types
              from p in t.GetProperties()
              group p by p.Name into pg
              where pg.Count() == types.Length
              select pg.Key).ToList();
Cevap 09/12/2008 saat 19:02
kaynak kullanıcı

oy
0

İyi,

Sen IComparable benzer arayüzde oluşturmak ama bunun yerine böylece onların özellik adlarını karşılaştırmak için yansıma kullanmak uygulamak sınıfları sonra IPropertyComparable gibi bir şey diyeceğiz ve olabilir ...

public int Compare(T x, T y)
{
     PropertyInfo[] props = x.GetType().GetProperties();

     foreach(PropertyInfo info in props)
     {
          if(info.name == y.GetType().Name)
          ....
     }

     ...

Ben gerisini anlamaya izin vereceğim. Muhtemelen belki LINQ kullanmak, yine de biraz daha şık olabilirdi ...

  • Mat
Cevap 09/12/2008 saat 18:00
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more