简体   繁体   中英

Can I use generic getter/setter methods on multiple lists of same base types in C#

I want to know if there is a way I can create generic getter and setter methods for the below code.

Currently the setter checks the actual type of the input object and adds it to the relevant list. It feels like a bad approach to me, but I'd like to know if there is a better way.

I can't use any other data structures like a dictionary because I am using a serialisation system that can only serialise simple collection types like Lists and arrays, hence all the individual lists.

public abstract class BaseStyleType {}
public class ImageStyle  : BaseStyleType {}
public class TextStyle   : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc

public class GlobalStyle : ASerializedObject
{
    public List<ImageStyle>  ImageStyles     = new List<ImageStyle>();
    public List<TextStyle>   TextStyles      = new List<TextStyle>();
    public List<ButtonStyle> ButtonStyles    = new List<ButtonStyle>();
    //... etc

    // Setter
    public void SetStyle(BaseStyleType inStyle)
    { 
        if (inStyle as ImageStyle != null)
            ImageStyles.Add((ImageStyle)inStyle);
        else if (inStyle as TextStyle != null)
            TextStyles.Add((TextStyle)inStyle);
        else if (inStyle as ButtonStyle != null)
            ButtonStyles.Add((ButtonStyle)inStyle);
        //... etc
    }

    // Getter
    public T GetStyle<T>(int index)
    {
        //...?
    }
}

Thanks

Just because you can't use things for serialization purposes shouldn't prevent you from actually using them.

The advantage to the following solution is you can infinitely create derives classes from BaseStyleType (or other super types) and you'd only have to create the properties to access the dictionary.

public abstract class BaseStyleType {}
public class ImageStyle  : BaseStyleType {}
public class TextStyle   : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}

// NOT THREAD SAFE
public class GlobalStyle
{
   // 
   private Dictionary<Type,List<BaseStyleType>> _lists = 
     new Dictionary<Type,List<BaseStyleType>>();

   // Not sure why you'd use Fields here...
   public IEnumerable<ImageStyle> ImageStyles
   {
     get 
     {
       IEnumerable<ImageStyle> result = null;
       List<BaseStyleType> list;
       if (_lists.TryGetValue(typeof(ImageStyle), out list))
       {
         result = list.Cast<ImageStyle>();
       }
       return result;
     }
   }
   //etc
   //public List<ImageStyle>  ImageStyles     = new List<ImageStyle>();
   //public List<TextStyle>   TextStyles      = new List<TextStyle>();
   //public List<ButtonStyle> ButtonStyles    = new List<ButtonStyle>();


   // Setter
   public void SetStyle<T>(T inStyle)
       where T : BaseStyleType
   {
       List<BaseStyleType> list;
       if (_lists.TryGetValue(typeof(T), out list))
       {
         list.Add(inStyle);
       }
       else
       {
           list = new List<BaseStyleType>();
           list.Add(inStyle);
           _lists.Add(typeof(T), list);
       }
   }
}

I see two ways at least:

1) You got a simple, flat herarchy. Make only lists of BaseStyleType. Let covariance and automatic upcasting take care of the details.

2) Modify your code somewhat like that:

public abstract class BaseStyleType {}
public class ImageStyle  : BaseStyleType {}
public class TextStyle   : BaseStyleType {}
public class ButtonStyle : BaseStyleType {}
//...etc

public class GlobalStyle <List1Type, List2Type, List3Type, ... > : ASerializedObject
{
    public List<List1Type>  ImageStyles     = new List<List1Type>();
    public List<List2Type>   TextStyles      = new List<List2Type>();
    public List<List3Type> ButtonStyles    = new List<List3Type>();
    //... etc

    // Setter
    public void SetStyle(BaseStyleType inStyle)
    { 
        if (inStyle as ImageStyle != null)
            ImageStyles.Add((ImageStyle)inStyle);
        else if (inStyle as TextStyle != null)
            TextStyles.Add((TextStyle)inStyle);
        else if (inStyle as ButtonStyle != null)
            ButtonStyles.Add((ButtonStyle)inStyle);
        //... etc
    }

    // Getter
    public T GetStyle<T>(int index)
    {
        //...?
    }
}

The problem with long type lists is that you end up having to use lines like GlobalStyle <ImageStyle , TextStyle, ButtonStyle> every single time a the type is needed (field types, return types, paramters, etc.). Starting with two generic placeholders, it is usually a good idea to make a type alias.

using CustomGlobalStyle = GlobalStyle <ImageStyle, TextStyle, ButtonStyle>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM