Access the declaring class in a custom attribute? - c#

I've created a custom attribute where I want to access the the declaring class of the custom attribute property.
For example:
public class Dec
{
[MyCustomAttribute]
public string Bar {get;set;}
}
Here I would like (in the the cass of MyCustomAttribute) to get the type of the declaring class (Dec).
Is this by any means possible?
EDIT: Thanks for the replies everyone. I learned something new today.

As I've written, attributes are instantiated only when you request them with type.GetCustomAttributes(), but at that time, you alread have the Type. The only thing you can do is:
[AttributeUsage(AttributeTargets.Property)]
public class MyCustomAttribute : Attribute
{
public void DoSomething(Type t)
{
}
}
public class Dec
{
[MyCustomAttribute]
public string Bar { get; set; }
}
// Start of usage example
Type type = typeof(Dec);
var attributes = type.GetCustomAttributes(true);
var myCustomAttributes = attributes.OfType<MyCustomAttribute>();
// Shorter (no need for the first var attributes line):
// var myCustomAttributes = Attribute.GetCustomAttributes(type, typeof(MyCustomAttribute), true);
foreach (MyCustomAttribute attr in myCustomAttributes)
{
attr.DoSomething(type);
}
so pass the type as a parameter.

No, it is not - except for by build-time tools like PostSharp, Roslyn, etc.
You need to find a different approach - perhaps passing a Type in as a constructor argument; or (more likely), but having whatever logic you want to be attribute-based be aware of the declaration context; i.e. assuming MyCustomAttribute has a Foo() method, make it Foo(Type declaringType) or similar.

This might also work:
class MyCustomAttribute : Attribute
{
public Type DeclaringType { get; set; }
}
public class Dec
{
[MyCustomAttribute(DeclaringType=typeof(Dec))]
public string Bar { get; set; }
}

Related

C# How to return an instance of the type of subclass from function?

I have a bunch of classes that formulate various variations of items. I currently have a class like this:
public class Item {
public ItemFile file { get; set;}
public ItemCalendar calendar { get; set;}
public ItemWebsite website { get; set;}
}
ItemFile etc are classes made using Entity Framework and map to the database tables that provide the information relating to that type of item. The item class only has one of the internal properties actually instantiated.
I can see the number of items growing to around 25 or more. I don't feel right making the view model containing 25 properties where 24 of them are null with only one being not null.
I want something that can work with entity framework and return a class that can return only it's actual type. Therefore if I ask for the variation of the item I would get back ItemFile for files and ItemCalendar for calendars.
I've tried something like this:
public class Item
{
public ItemBase item { get; set; }
}
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
But then I don't know how to return ItemFile as public typeName is an error.
I then tried:
public class Item
{
public ItemBase<ItemFile> item { get; set; }
}
public class ItemBase<T>
{
public T ItemInstance { get; set; }
}
But to get that to work, I had to hardcore FileItem in the <> on the item class which goes back into knowing the type before hand.
Is there anyway to get this to work? Bonus points if it can work with entity framework as I'm pulling back the classes from there. Worst comes to worst if it doesn't work entity framework wise is I can pull it all and then convert it into the form that answers the question.
If the title of the question is wrong, feel free to edit. I wasn't sure how to ask.
tl;dr version: I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
Edit 1:
I forgot to show my inheritence example. I've tried this but also got stuck with something similar to the above.
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
public class ItemFile : ItemBase
{
public String FileName { get; set; }
}
public class Test
{
public void testFunction()
{
//Made this just so the compiler didn't complain.
ItemFile testFile = new ItemFile();
//I can use a function to get the item base.
ItemBase baseItem = testFile;
//How do I do this? Use a function to get the ItemFile from the instance.
ItemFile finalItem = baseItem.GetInstance();
}
}
I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
<> (generics) are the mechanism by which a function can explicitly return more than one type. Without generics the function returns whatever type it says it returns.
object SomeFunction() // Returns an object
ItemBase SomeOtherFunction () // returns ItemBase
In the above examples, SomeFunction can still return any type (because all types inherit from object.) But it won't be explicit. All you know for sure is that it's an object.
Similarly, SomeOtherFunction can return an ItemBase or any class that inherits from ItemBase. But that's all you know about it.
Ideally you don't want to have functions returning one type (like object or ItemBase) and then cast the result of the function to another more specific type. The function should return what you want, and you should want what the function returns. Generics help with that. For example:
public TItem Instance<TItem>() where TItem : ItemBase
allows a function to return a specified type as long as it is an ItemBase or inherits from one.
This last comment is going to seem odd or useless but it's the truth. If you find yourself in a scenario where the above rules don't work and you need to be able to do something that you can't do or shouldn't do, go back and rethink why you're trying to do that. That's where the real problem is.
That means you probably need to go back a step and get yourself out of the situation where you're trying to work against the language. What are you trying to accomplish and how can you do it in a way that works with the language, not against it?
I believe this is about as close as you're going to get.
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
EFTypeData itemData = GetItemData();
var asmName = Assembly.GetExecutingAssembly().GetName().Name;
var type = Type.GetType($"ConsoleApplication1.{itemData.TypeName}, {asmName}");
var instance = Activator.CreateInstance(type);
var item = new Item<Object>()
{
ItemBase = instance
};
}
private static EFTypeData GetItemData()
{
return new EFTypeData() { TypeName = "ItemFile" };
}
}
class EFTypeData
{
public string TypeName { get; set; }
}
class Item<T> where T: class
{
public T ItemBase { get; set; }
}
class ItemFile
{
public string FileName { get; set; }
}
}
This will, given a string "ItemFile", create an instance and assign it to Item. If you run this and inspect item, you have
The big caveat to this is that at compile-time, all you have is an Object as your ItemBase. And without hard-coding your Type (i.e. var item = new Item<ItemFile>();), you're never going to know more.
That said, with this method you are perfectly clear to iterate over fields and such using Reflection. But this is a limitation of this level of run-time object manipulation.

What is the best way to define a static property which is defined once per sub-class?

I wrote the following console app to test static properties:
using System;
namespace StaticPropertyTest
{
public abstract class BaseClass
{
public static int MyProperty { get; set; }
}
public class DerivedAlpha : BaseClass
{
}
public class DerivedBeta : BaseClass
{
}
class Program
{
static void Main(string[] args)
{
DerivedBeta.MyProperty = 7;
Console.WriteLine(DerivedAlpha.MyProperty); // outputs 7
}
}
}
As this console app demonstrates, the MyProperty property exists once for all instances of BaseClass. Is there a pattern to use which would allow me to define a static property which will have allocated storage for each sub-class type?
Given the above example, I would like all instances of DerivedAlpha to share the same static property, and all instances of DerivedBeta to share another instance of the static property.
Why am I trying to do this?
I am lazily initializing a collection of class property names with certain attributes (via reflection). The property names will be identical for each derived class instance, so it seems wasteful to store this in each class instance. I can't make it static in the base class, because different sub-classes will have different properties.
I don't want to replicate the code which populates the collection (via reflection) in each derived class. I know that one possible solution is to define the method to populate the collection in the base class, and call it from each derived class, but this is not the most elegant solution.
Update - Example of what I'm doing
At Jon's request, here's an example of what I'm trying to do. Basically, I can optionally decorate properties in my classes with the [SalesRelationship(SalesRelationshipRule.DoNotInclude)] attribute (there are other attributes, this is just a simplified example).
public class BaseEntity
{
// I want this property to be static but exist once per derived class.
public List<string> PropertiesWithDoNotInclude { get; set; }
public BaseEntity()
{
// Code here will populate PropertiesWithDoNotInclude with
// all properties in class marked with
// SalesRelationshipRule.DoNotInclude.
//
// I want this code to populate this property to run once per
// derived class type, and be stored statically but per class type.
}
}
public class FooEntity : BaseEntity
{
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_A { get; set; }
public int? Property_B { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_C { get; set; }
}
public class BarEntity : BaseEntity
{
public int? Property_D { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_E { get; set; }
public int? Property_F { get; set; }
}
Desired end result
Accessing FooEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_A",
"Property_C"
}
Accessing BarEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_E"
}
Two possible approaches:
Use attributes; decorate each subclass with an attribute, e.g.
[MyProperty(5)]
public class DerivedAlpha
{
}
[MyProperty(10)]
public class DerivedBeta
{
}
That only works when they're effectively constants, of course.
Use a dictionary:
var properties = new Dictionary<Type, int>
{
{ typeof(DerivedAlpha), 5) },
{ typeof(DerivedBeta), 10) },
};
EDIT: Now that we have more context, Ben's answer is a really good one, using the way that generics work in C#. It's like the dictionary example, but with laziness, thread-safety and simple global access all built in.
Jon has a good solution as usual, although I don't see what good attributes do here, since they have to be explicitly added to every subtype and they don't act like properties.
The Dictionary approach can definitely work. Here's another way to do that, which explicitly declares that there will be one variable per subclass of BaseEntity:
class FilteredProperties<T> where T : BaseEntity
{
static public List<string> Values { get; private set; }
// or static public readonly List<string> Values = new List<string>();
static FilteredProperties()
{
// logic to populate the list goes here
}
}
The drawback of this is that it's rather difficult to pair with a GetType() call such as you might use in methods of BaseEntity. A Dictionary, or wrapper thereto which implements lazy population, is better for that usage.
I just recently needed this same thing and came across this question. I think Jon's and Fried's ideas to use a Dictionary are on the right track but don't quite hit what I was looking for so I thought I'd show my own complete and very easy to extend implementation.
public class TypeStaticProperty<T>
{
T _defaultValue;
Dictionary<Type, T> _values = new Dictionary<Type, T>();
public TypeStaticProperty(T defalutValue = default)
{
_defaultValue = defalutValue;
}
public T Get(object caller)
{
lock (_values)
{
if (_values.TryGetValue(caller?.GetType(), out T val))
return val;
else
return _defaultValue;
}
}
public void Set(object caller, T val)
{
lock (_values)
_values[caller?.GetType()] = val;
}
}
And to demonstrate:
class TestBaseClass
{
static TypeStaticProperty<int> _property = new TypeStaticProperty<int>();
public int Property
{
get => _property.Get(this);
set => _property.Set(this, value);
}
}
class TestClass1 : TestBaseClass
{
}
class TestClass2 : TestBaseClass
{
}
class Program
{
static void Main(string[] args)
{
TestClass1 test1a = new TestClass1();
TestClass1 test1b = new TestClass1();
test1a.Property = 1;
test1b.Property = 2;
TestClass2 test2a = new TestClass2();
TestClass2 test2b = new TestClass2();
test2a.Property = 3;
test2b.Property = 4;
Console.WriteLine($"test1a.Property = {test1a.Property}");
Console.WriteLine($"test1b.Property = {test1b.Property}");
Console.WriteLine($"test2a.Property = {test2a.Property}");
Console.WriteLine($"test2b.Property = {test2b.Property}");
}
}
Output:
test1a.Property = 2
test1b.Property = 2
test2a.Property = 4
test2b.Property = 4
So while you still need a class instance to access and set the property, the value will always be the same across all instances of that precise type. (This includes generics too; Foo<int> will be seen as a different type than Foo<string>). This has the huge advantage over Fried's example in that you don't need to know at compile time the precise type whose "static" value you're looking for when accessing or setting.
PS - For full disclosure, this was heavily inspired by the WPF source code, which uses a very similar pattern for DependencyProperty's and all kinds of other internal bells and whistles designed to improve performance and reduce memory footprint.

Specify interface member not by name but type

I have a lot of similar classes generated by svcutil from some external WSDL file. Any class has a Header property and string property which named class name + "1".
For instance, I have classes: SimpleRequest that has Header property and SimpleRequest1 property.
Another one is ComplexRequest that has Header property and ComplexRequest1 property.
So, I want to create a common interface for such classes. So, basically I can define something like that:
interface ISomeRequestClass {
string Header;
// here is some definition for `class name + "1"` properties...
}
Is it possible to define such member in interface?
Here is post edit goes...
Here is sample of generated class:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class SimpleRequest
{
public string Header;
[System.ServiceModel.MessageBodyMemberAttribute(Name="SimpleRequest", Namespace="data", Order=0)]
public SimpleRequestMsg SimpleRequest1;
public SimpleRequest()
{
}
public SimpleRequest(string Header, SimpleRequestMsg SimpleRequest1)
{
this.Header = Header;
this.SimpleRequest1 = SimpleRequest1;
}
}
POST EDIT 2
I changed definition of this annoying +1 property to represent real actual picture. It's all has different class types. So how can I pull it out to common interface?
POST EDIT 3
Here is coupled question that could bring more clarify.
EDIT (after seeing your code sample): Technically speaking, your code does not have a Header property, it has a Header field. This is an important difference, since you cannot specify fields in an interface. However, using the method described below, you can add properties to your classes that return the field values.
Is it possible to define such member in interface?
No, interface names cannot be dynamic. Anyway, such an interface would not be very useful. If you had an instance of class ISomeRequestClass, what name would you use to access that property?
You can, however, use explicit interface implementation:
interface ISomeRequestClass {
string Header { get; set; }
string ClassName1 { get; set; }
}
class SomeClass : ISomeRequestClass {
string Header { ... }
string SomeClass1 { ... }
// new: explicit interface implementation
string ISomeRequestClass.ClassName1 {
get { return SomeClass1; }
set { SomeClass1 = value; }
}
}
You could define your interface more generally:
interface ISomeRequestClass {
string HeaderProp {get; set;}
string Prop {get; set;}
}
And your concrete classes could be extended (in an extra code file) by mapping interface members to class fields like so:
public partial class SimpleRequest : ISomeRequestClass
{
public string HeaderProp
{
get
{
return Header;
}
set
{
Header = value;
}
}
public string Prop
{
get
{
return SimpleRequest1;
}
set
{
SimpleRequest1= value;
}
}
}
Putting aside for a moment the naming of your classes and properties.
If you're looking to create an interface with a property relevant to your specific +1 type, you have a couple of options.
Use a base class for your +1's
If both of your +1 classes inherit from the same base class you can use this in your interface definition:
public interface IFoo
{
[...]
PlusOneBaseType MyPlusOneObject{get;set;}
}
Create a generic property on your interface
This method allows you to specify the type for the +1 property as a generic parameter:
public interface IFoo<TPlusOneType>
{
[...]
TPlusOneType MyPlusOneObject{get;set;}
}
Which you might use like:
public class SimpleRequest : IFoo<SimpleRequest1>
{
[...]
}
Update
Given that your classes are partial classes, you could always create a second (non machine generated) version of the partial class that impliments your interface.
You mentioned svcutil so I assume you are using these classes as WCF DataContracts?
If that is the case then you could make use the name property of DataMemberAttribute.
interface IRequest
{
string Header { get; set; }
string Request1 { get; set; }
}
[DataContract]
class SimpleRequest : IRequest
{
[DataMember]
public string Header { get; set; }
[DataMember(Name="SimpleRequest1"]
public string Request1 { get; set; }
}
[DataContract]
class ComplexRequest : IRequest
{
[DataMember]
public string Header { get; set; }
[DataMember(Name="ComplexRequest1"]
public string Request1 { get; set; }
}
If you are concerned giving yourself more work when you regenerate the code at some point in the future, then I recommend you write a PowerShell script to do this transformation automatically. After all svcutil is just a script written by some guy at Microsoft. It is not magic or "correct" or "standard". Your script can make a call to scvutil and then make a few quick changes to the resulting file.
EDIT (After seeing your edit)
You are already using MessageBodyMemberAttribute's Name property so just change this:
public string SimpleRequest1;
To
public string Request1;
Do you actually need these classes to have a common interface? I'd be tempted to instead create a wrapper interface (or just a concrete class) which could then use reflection to access the fields in question:
// TODO: Make this class implement an appropriate new interface if you want
// to, for mocking purposes.
public sealed class RequestWrapper<TRequest, TMessage>
{
private static readonly FieldInfo headerField;
private static readonly FieldInfo messageField;
static RequestWrapper()
{
// TODO: Validation
headerField = typeof(TRequest).GetField("Header");
messageField = typeof(TRequest).GetField(typeof(TRequest).Name + "1");
}
private readonly TRequest;
public RequestWrapper(TRequest request)
{
this.request = request;
}
public string Header
{
get { return (string) headerField.GetValue(request); }
set { headerField.SetValue(request, value); }
}
public TMessage Message
{
get { return (TMessage) messageField.GetValue(request); }
get { messageField.SetValue(request, value); }
}
}
You could use expression trees to build delegates for this if the reflection proves too slow, but I'd stick to a simple solution to start with.
The advantage of this is that you only need to write this code once - but it does mean creating a wrapper around the real request objects, which the partial class answers don't.

Trying to get a literal via reflection

Suppose I have a the following code:
Container.cs
public class Container
{
public readonly string IdType;
public Container( string aIdType )
{
IdType = aIdType;
}
}
SuperContainerA .cs
public class SuperContainerA : Container
{
public SuperContainerA( /*x parameters*/ ) : base("A") {}
}
SuperContainerB.cs
public class SuperContainerB : Container
{
public SuperContainerB( /*y parameters*/ ) : base("B") {}
}
SuperContainerToTheInfinityAndBeyond.cs
public class SuperContainerB : Container
{
public SuperContainerB( /*y parameters*/ ) : base("It's Over 9000!") {}
}
Based on that, what I'm trying to retrieve is the "A" and "B" that are being sent to the TypeId from the constructor.
The catch here is... I need to retrieve those values during the initialization of the program, before creating an instance of those classes, so I thought that using reflection is my best bet here. (Note: Creating an instance of the classes to retrieve the value would be valid if the number of parameters for each constructor would be the same, but they can change. :()
Is it possible to use reflection to check the literals of my source code and/or Assemblies? (If I can see something like the source code, then I can use Regex to get the value.)(Note: Including the sources as resource files to my program is not an option :P)
I'm thinking of declaring constants to hold the value and force an naming rule on then, so that I could use reflection later to grab then back. Something like ...
public class SuperContainerA
{
public const string ctIdType = "A";
}
public class SuperContainerB
{
public const string ctIdType = "B";
}
... But I'm not sure if this is the best approach to this problem, since I won't have anything to help me check if these consts have been declared and if they got the proper name during compile time.
Actually, if the language had some kind of static inheritance, this would help a lot in this situation, but I hear some programmers complaing that static inheritance is more of an head ache than a cure.
Anyway, I'm searching for alternatives. Any idea is welcome.
Attributes to the rescue!
public class IdTypeAttribute: Attribute
{
public string IdType { get; private set; }
public IdTypeAttribute(string idType)
{
IdType = idType;
}
}
[IdType("B")]
public class SuperContainerB: Container
{
// whatever you like...
}
You can then access the Attribute via reflection. Easy enough to do...
var type = typeof(SuperContainerB);
var attribute = (IdTypeAttribute)type.GetCustomAttributes(
typeof(IdTypeAttribute), false)[0];
var idType = attribute.IdType;
Why not simply use the concrete type to look up the string value that you seem to want associated with it?
public class SuperA : Container
{
public string IdType { get { return IdTypeFactory.Get( GetType() ); } }
}
public static class IdTypeFactory
{
public static string Get( Type containerType ) { ... }
}
The primary benefit of this solution would be to gather all your string literals in one central location. Alternatively, go with the abstract super class.

Extending using C# generics?

I want to create an extendable nested structure and it seems like I should be able to do this using generics, though I may not be using them "properly".
I want to be able to create child classes from GroupType and/or OptionType. The problem is that I can't perform the new operation on the generic types even though I specified they could only be of a certain base type.
Is there any way to do what I'm trying to do?
public class AllInfo<GroupType, OptionType>
where GroupType: GroupBase<OptionType>
where OptionType: OptionBase
{
public List<string> Names { set; get; }
public List<GroupType> Groups { set; get; }
public AllInfo()
{
DataSet ds = DatabaseRetreival();
this.Groups.add(new GroupType(ds["Name"], ds["Type"]));
}
}
public class GroupBase<OptionType>
where OptionType: OptionBase
{
public string Name { set; get; }
public string Type { set; get; }
public List<OptionType> Options { set; get; }
public GroupBase(string name, string type)
{
this.Name = name;
this.Type = type;
DataSet ds = DatabaseRetreival(this.Type);
this.Options.Add(new OptionType(ds["Name"]));
}
}
public class OptionBase
{
public string Name { set; get; }
public OptionBase(string name)
{
this.Name = name;
}
}
You have to specify the classes must have a default constructor.
where GroupType: GroupBase<OptionType>, new()
View this article and jump down to the section titled Generic Constraints.
You can't specify which constructors a generic class should have. The constructors are not inherited, so even if the base class that you specified has that constructor, a class that derives from it doesn't have to have that constructor.
The only constructor that you can require is the parameterless constructor:
where GroupType: GroupBase<OptionType>, new()
As that only let's you use the parameterless constructor, you would also use a virtual method for putting the data in the object, for example:
GroupType group = new GroupType();
group.Init(ds["Name"], ds["Type"]);
this.Groups.add(group);
The compiler cannot allow that, because it cannot guarantee that the OptionType has a constructor with the right signature. But you can pass a factory function instead of invoking the constructor directly:
public class Foo<T>
{
private List<T> myObjects;
public Foo(Func<string, T> factory))
{
myObjects = new List<T>();
foreach (string s in GetDataStrings())
myObjects.Add(factory(s));
}
}
So if you have a Bar class with a constructor taking a string, you do this:
Func<string,Bar> barFactory = x => new Bar(x);
var foo = new Foo<Bar>(barFactory);
The problem you have is foundationally based in very high amounts of class coupling that you are trying to mitigate with inheritance/generics. I suggest you re-examine why you feel this is necessary. This quest will eventually lead you to interfaces, service-based programming, and IoCs like Ninject or Castle Windsor.
However, if you want a quick fix that further increases code complexity (because you don't have non-complex options here aside from changing your coding philosophy), use an abstract/virtual method, maybe call it Bind(), instead of constructors.
[bolded for tl;dr]

Categories