How to Pass Objects into an Attribute Constructor

How to pass objects into an attribute constructor

The values into attributes are limited to simple types; for example, basic constants (including strings) and typeof... you can't use new or other more complex code. In short; you can't do this. You can give it the type though:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)]

i.e. the PropertyValidation ctor takes a Type, and use Activator.CreateInstance inside the code to create the object. Note that you should ideally just store the string internally (AssemblyQualifiedName).

From ECMA 334v4:

§24.1.3 Attribute parameter types

The types of positional and named
parameters for an attribute class are
limited to the attribute parameter
types
, which are:

  • One of the following types: bool, byte, char,
    double, float, int, long, short, string.
  • The type object.
  • The type System.Type.
  • An enum type, provided it has public accessibility and the
    types in which it is nested (if any)
    also have public accessibility.
  • Single-dimensional arrays of the above
    types.

and

§24.2 Attribute specification

...

An expression E is an
attribute-argument-expression if all
of the following statements are true:

  • The type of E is an attribute
    parameter type (§24.1.3).
  • At compile-time, the value of E can be
    resolved to one of the following:

    • A constant value.
    • A typeof-expression (§14.5.11) specifying a non-generic
      type, a closed constructed type
      (§25.5.2), or an unbound generic type
      (§25.5).
    • A one-dimensional array of
      attribute-argument-expressions.

Pass instance of Class as parameter to Attribute constructor

That's totally impossible. Attributes are baked into the metadata of the assembly at compile-time so talking about passing an instance of a class to an attribute doesn't make any sense because instances exist only at runtime.

On the other hand attributes are always consumed by reflection, so I guess that at the moment you are checking for the presence of this custom attribute on the class metadata you could use the the instance.

Passing an array of objects to Attribute constructor

It's because an array of string is a compile-time constant whereas an array of Person is not. This isn't a bug, it's a limitation. The best way around it, that I've found, is by using reflection to set the attributes properties on creation of the object - but it's not pretty.

C# how to extend and pass a parameter to an attribute

It’s not clear what you want to do with the data. You don’t have this type’s instance at the time you create the attribute. This attribute isn’t an instance of an object so you cannot pass any arguments so you must create the object at runtime, and you can do so with reflection.

You can use:

IItemsSource myObject = Activator.CreateInstance<IItemsSource>(obj1, obj2,...);

Update:
As I understand, you want to pass the type and then values to add to the list so you could add

public interface IItemsSource
{
List<string> GetValues();
}
class ItemsSourceAttribute : Attribute
{
public IItemsSource Instance { get; set; }
public ItemsSourceAttribute(Type type, params string[] listParams)
{
if (!typeof(IItemsSource).IsAssignableFrom(type))
throw new ArgumentException($"IItemsSource is not assignable from {type.Name}.");

Instance = (IItemsSource) Activator.CreateInstance(type, listParams);
}
}

public class MyCustomItemsSource : IItemsSource
{
private List<string> _privateList;

public MyCustomItemsSource(params string[] list)
{
_privateList = list.ToList();
}

public List<string> GetValues()
{
// _privateList will start with a value of [abc, 123], as we passed on the constructor.
_privateList.Add("test");
// now [abc, 123, test]
return _privateList;
}
}

And then you could add items to the list like that:

[ItemsSource(typeof(MyCustomItemsSource), "abc", "123"]

Hopefully I got it right. Please comment if you need any adjustments. I wrote this without testing as I'm not with VS on this machine at this moment.

How to get constructor named arguments from attribute

Currently all your parameters are positional ones, so they are returned in ConstructorArguments.

As written in the docs:

Each non-static public read-write field and property for an attribute class defines a named parameter for the attribute class.

Changing your MenuItemAttribute to for example:

    public class MenuItemAttribute : Attribute
{
ApplicationCategoryEnum ApplicationCategory { get; }
public string ControllerDisplayName { get; set; }
public bool IsDefaultRoute { get; set; }

public MenuItemAttribute(ApplicationCategoryEnum applicationCategory)
{
ApplicationCategory = applicationCategory;
}
}

And usage

[MenuItem(ApplicationCategoryEnum.CONTROLPANEL, ControllerDisplayName = "asdsa", IsDefaultRoute = true)]

Will give you 2 elements in NamedArguments collection.

How to pass an instance of a class into attributes within its constructor and have those attributes access initialized attributes?

You want to pass self (the instance of Foo being initialized) to Bar and Baz, not the class Foo itself.

class Foo(object):
a=9
def __init__(self):
self.bar = Bar(self)
self.baz = Baz(self)

If this is correct, then running your code should produce the output 72.

Passing attributes and methods of object inside another object

It's not totally clear, but I think this is what you want:

class PrimaryClass:
def __init__(self, param1, param2):
self.attr1 = param1
self._attr2 = do_something(param2)
def primary_method(self):
sec_cls = SecondaryClass(self)
sec_cls.secondary_method()
def __private_method(self):
do_something_else()

class SecondaryClass:
def __init__(self, primary):
self.primary = primary

def secondary_method():
print(self.primary.attr1)
print(self.primary._attr2)

To hide SecondaryClass from users of primary_module, use:

from secondary_module import SecondaryClass as _SecondaryClass

See Hide external modules when importing a module (e.g. regarding code-completion)



Related Topics



Leave a reply



Submit