locked
AvailableItemAttribute - How to pass a collection of items? RRS feed

  • Question

  • User1561875705 posted

    I would like to create a new attribute which both populates the ListItems of controls such as the DropDownList and ListBox, and also validates that the data returned is a value within the collection.   The source of the collection might come from several possible sources such as a collection property, a Dictionary or a NameValueCollection.

    Unfortunately, as I've learned, you cannot pass an object as a parameter to attributes.    I've considered the following:

    1) Pass a delimited string:   <AvailableItems("Red=1|Blue=2|Green=3")> _   ...  This works, but seems very clumsy.

    2) Pass a Enumerator:  <AvailableItems(ColorType)> _ ...  The problem here is that's not very display friendly, and there can be no Text/Value pairing.

    3) Pass a property name and use reflection to retrieve the object:   <AvailableItems("MyClass.MyColorProperty")> _  ... Not sure how well this would work.

    4) Pass the name of a Cache or Application key:  <AvailableItems("MyCacheKey")> _ ... This might work well

    Is there a better way that I haven't thought of?  Is there any way to pass an object as a attribute parameter?

     Also, how would you validate that the data returned is one of the items?

    Friday, August 29, 2008 2:19 AM

All replies

  • User188291263 posted

     Why just dont return dictionary or NameValue as property??? Then you can create your custom field?

    Also,if you want to pass Enum with description,you can put attributes like Description("test") on Enum values.

    Friday, August 29, 2008 10:37 AM
  • User1561875705 posted

    That's actually what I'm trying to do, but unless I'm missing something, you can't pass a dictionary as a parameter to an attribute.   It give the error, "constant expression is required".    You can't pass the dictionary through the constuctor nor to a field or property.  

    That would be perfect if we could, as all of our lookup data comes from dictionarys or key/value type collections.    I think that we've already dismissed the possibility of using an enum, because you can't have a name and a value if they're both strings, and the name cannot have spaces or special characters.

     At this point, I'm thinking that the best option might be to pass in a property name as a string, and use reflection to call it...

    <AvailableItems("LookupData.StatusCodes")>_

    then use reflection so call the property and retrieve the dictionary, assuming that 'LookupData' is the static class, and StatusCodes is a property that returns a dictionary.

    Any other ideas would be appreciated.

    Friday, August 29, 2008 5:02 PM
  • User-330204900 posted

    Try this, I know its in c# but you should be able to work it out [:)] 

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class TablePermissionsAttribute : System.Attribute
    {
    	// this property is required to work with "AllowMultiple = true" ref David Ebbo
    	// As implemented, this identifier is merely the Type of the attribute. However, 
    	// it is intended that the unique identifier be used to identify two 
    	// attributes of the same type.
    	public override object TypeId { get { return this; } }
    
    	/// <summary>
    	/// Constructor
    	/// </summary>
    	/// <param name="permission"></param>
    	/// <param name="roles"></param>
    	public TablePermissionsAttribute(Permissions permission, params String[] roles)
    	{
    		this._permission = permission;
    		this._roles = roles;
    	}
    
    	private String[] _roles;
    	public String[] Roles
    	{
    		get { return this._roles; }
    		set { this._roles = value; }
    	}
    
    	private Permissions _permission;
    	public Permissions Permission
    	{
    		get { return this._permission; }
    		set { this._permission = value; }
    	}

     in c# we would use the params key word to set this up, see the vb that a c#->vb converter did:

     

    Public Sub New(ByVal permission As Permissions, ParamArray roles As String()) 
        Me._permission = permission 
        Me._roles = roles 
    End Sub 
     

     

    Hope this helps [:D]
    Saturday, August 30, 2008 4:27 PM
  • User1561875705 posted

    Thanks for this suggestion.  Using the ParamArray is not somthing we had considered.  

     Though this will help in some cases where the array is a small, static set of items, we still need a way that large sets of items can be passed in a dynamic way.   After much research, I've concluded that there is no way to pass an object like an array or dictionary to a parameter, unless the attribute declaration contains the expression.

     For the time being, we've settled on using a delimited parameter string, ex:  <AvailableItems("Red=R|Blue=B|Green=G")> ... that way a property could still be called that dynamically created the string, ex:  <AvailableItems(LookupData.ColorsString)>

     

    Tuesday, September 2, 2008 6:00 PM