Custom attribute only on specific classes - c#

I would like to define a constrait on my custom (PostSharp) attribute. My goal is to get error or warning while compile time, if class X dont implements Y interface but it has my attribute.
So this should work:
[MyAttributeOnlyForY]
public class X : Y { ... }
but this should break the compile process:
[MyAttributeOnlyForY]
public class X { ... }
How is it possible?
The reason
This attribute works like an aspect (this is PostSharp attribute), and I want to be sure that the weaved class provides all needed information for this attribute.
I want to avoid null result on
(eventArgs.Instance as ILoggerServiceOwner)
and I think complie time checking is a good practice.
Solution
I've found a perfect start here: Validating attribute usage with PostSharp Aspects

You could use the PostSharp method CompileTimeValidate and use reflection to check if type has a derived type. However, it may be computationally expensive do look for all types in the assembly.

I think this is not possible.
A better solution might be to use the Obsolete attribute on your custom attribute constructor to warn that the target class should implement the interface Y.

Related

Conditional interface

For a project I'm on I'm unfortunately stuck with .NET 2.0 (many of our target machines are still Windows XP), which means no Optional type as Nuget's Optional library requires .NET 3.5.
Fortunately, rolling your own Optional type is pretty easy, but I've encountered one issue.
I would like something like the following:
class Optional<T> : (IComparable<Optional<T>> when T : IComparable<T>)
That is, I want my Optional type to implement Comparable, but only when the underlying type is Comparable.
The above syntax is sadly not valid, but is there a way achieve what I'm looking for?
Indeed this problem isn't confined to Optional, it will apply to any container type one wants to define that can implement it's internal type's interfaces.
I do realise I could do this:
class Optional<T>
class ComparableOptional<T> : Optional<T>, Comparable<ComparableOptional<T>>
where T : Comparable<T>
But this seems a bit silly, as then we really have to go down this rabbit hole:
class Optional<T>
class EquatableOptional<T> :
Optional<T>,
IEquatable<EquatableOptional<T>>
where T : IEquatable<T>
class ComparableOptional<T> :
EquatableOptional<T>,
IComparable<ComparableOptional<T>>,
IEquatable<ComparableOptional<T>>
where T : IComparable<T>
Furthermore, if T is Enumerable, Optional<T> can also be Enumerable (returning an empty enumerator if there is no value) so then we've got even more classes.
As Enumerable is orthogonal to Equatable and Comparable, we'd really need the following classes:
class Optional
class EquatableOptional
class ComparableOptional
class EnumerableOptional
class EnumerableEquatableOptional
class EnumerableComparableOptional
to cover all cases. Add another orthogonal interface and you've got 12 classes.
Is there a less messy approach that allows me to define interfaces conditionally? This seems like a common issue with any collection.
What you want to do infringes on the intention of how generics work in C#.
You're essentially arguing that type safety should be used as type possibility. Which is against the current C# ideology where you know a type's definition (and which methods and properties it exposes) for a fact.
The correct approach would be to have a second ComparableOptional<T> which derives from Optional<T> but adds an additional constraint:
class ComparableOptional<T> : Optional<T> where T : Comparable<T>
There is no benefit to your suggestion, other than the lazy approach of wanting to mash two different classes together. Even if the language would allow you to do so, I see no discernible benefit to this approach (compared to ComparableOptional<T>) but it does introduce a whole range of runtime errors that you can now encounter.
class Optional<T> : (IComparable<Optional<T>> when T : IComparable<T>) {}
Suppose everything works the way you expect it to.
var optionalPerson = new Optional<Person>() { Person = myPerson };
var optionalPerson2 = new Optional<Person>() { Person = myPerson2 };
int result = optionalPerson.CompareTo(optionalPerson2);
Should this work? In C# currently, it doesn't. But according to you, it should be able to if Person : IComparable<Person>. Your argument should be something like this:
Since the compiler sees me use the type Person : IComparable<Person>, it should be able to deduce that Optional<T> must now implement IComparable<T> and therefore the CompareTo() should be available.
The solidity of your argument rests solely on the fact that you know for a fact (at compile time) that the type you're using implements the needed interface.
But what about this code:
public void DoSomething<T>(Optional<T> opt1, Optional<T> opt2)
{
int result = opt1.CompareTo(opt2);
}
Should this work? You can't know, since you don't know which type will be used! Compounding the issue even further:
public void DoSomething(string optionalType, object opt1, object opt2)
{
var castObj = Convert.ChangeType(opt1, Type.GetType(optionalType)));
var castObj2 = Convert.ChangeType(opt2, Type.GetType(optionalType)));
int result = castObj .CompareTo(castObj2);
}
This method passes the used type as a string. So now you would expect the compiler to check the value of the string to figure out whether or not the generic type constraint of the type that is represented in the string implements a particular interface.
WHat if that string is retrieved from a database or external web service? Is the compiler now required to have an active database/web connection before it can decide whether your code is valid?
This is running out of hand.
Your likely counterarguments:
As long as I only use this method with types that implement IComparable<T>, the compiler should not throw an error. When I use a type that does not implement IComparable<T>, it should throw an error on the int result line.
That is not intuitive, and is going to lead to developer confusion.
The compiler should always assume that conditional generic type constraints are true.
So how would you handle mutually exclusive conditional generic type constraints, which logically will never both be true?
Welcome to the world of debugging hell. This is bad practice for the same reason that you shouldn't use dynamic over strongly typed approaches: it makes code considerably harder to maintain and develop.
Such an approach requires much more runtime testing to ensure that you haven't made a mistake somewhere that will blow up in your face. And runtime testing is a flawed approach.

A lot of fields with the same attribute

I find myself writing a lot of this kind of stuff:
[SameAttribute]
ClassA fieldA;
[SameAttribute]
ClassB fieldB;
[SameAttribute]
ClassC fieldC;
...
Is there a syntax in C# that would allow me to mark several fields with the same attribute at once? May be there are coding conventions about this situation that would make this code less verbose and more readable?
Edit: Just to clarify, I don't want every field of the class to have this attribute, there's just a lot of them.
No. You will have to apply the [SameAttribute] to each field individually.
If you want SomeAttribute to apply to all fields in a class, it might be possible to apply the attribute to the entire class. However, even if SomeAttribute is allowed to target classes, its exact behavior when doing so is dependent on the implementation of SomeAttribute. Otherwise no, you have to apply the attribute to each field individually.
In addition to the other answers above, PostSharp, which allows "aspect-oriented programming" lets you define attributes that will apply to each member in a class. You can use it to make a custom attribute that would apply your desired attribute to all of the members.
There is nothing out of the box, that I know of, but you could use a Visual Studio add-in like ReSharper to create a live template to automatically add the Attribute you wish to use when you use a certain template
http://www.jetbrains.com/resharper/features/code_templates.html

Why does the VS Metadata view does not display explicit interface implemented members

The other day i was looking at C# Boolean struct metadata.
Boolean implements the interface IConvertible. But looking at Boolean's members i could not see most of the IConvertible members.
I've done some tests with some colleagues, including creating our own classes, and came to the conclusion that IConvertible must be implemented explicitly for Boolean.
The question is, why are they not visible? I understand it might be a 'by design decision' but i understand that it would add greater value if they were visible to anyone inspecting the metadata.
The tests were done in VS2010 .NET4.0
The reason is that those methods are there just to implement the I-interface and not to augment the class' public interface.
What I mean is that if you have the following:
public class MyClass : IConvertible
{
// implementation
}
You might want MyClass to be convertible, indeed, so you can pass references of it to methods that expect IConvertible:
public void DoSomethingWithConvertible(IConvertible conv)
But you might not want variables of type MyClass to expose the Convert methods. You simply don't want MyClass's public interface to have that method, then you implement the interface explicitly. That's the whole idea of the approach. This means the following is not allowed:
MyClass a = new MyClass();
a.Convert();
However, the following is still be allowed:
MyClass a = new MyClass();
((IConvertible)a).Convert();
The whole idea behind this is that even though we're using the exact same instance, a as MyClass doesn't have the method. A as IConvertible does have the method. Think of it as if you're allowing the instance to have split personality.
Usually I end implementing every interface implicitly. However, there are very specific situations where I'd implementing them explicitly exactly for the reasons outlined above.
BTW, thanks for the great question!
Because explicit interface implementation actually hides the implementation.
The metadata does indeed show the explicitly implemented. Do you mean intellisense and not metadata?
I'd say that's by design and help the developer of say Boolean to restrict the interface to a subset. By restricting what's suggested to use it also becomes visible what's considered abnormal usage. E.g. it's generally not advised to view a Boolean value as a specific numeric value but in certain cases it's handy to be able to do that anyways.
IDictinary<T,K> is another example. It implements IEnumerable<KeyValuePair<T,K>> making it possible to iterate over all the pairs in the collection and ICollation<KeyValuePair<T,K>>. So you can call Add on the dictionary given a KeyValuePair but usually you should use Add(K, key, T Value)
Try inspecting the class with a tool that provides read access to metadata. ILDASM for one and you can indeed find metadata of the explicitly implemented methods.
They are explicitly implemented. You can find all implemented convertables here: http://msdn.microsoft.com/en-us/library/system.boolean.aspx

Can an attribute discover what method it is applied to at run time?

Is there a way for an attribute that has been applied to a method to know what method it was applied to at run time?
[AttributeUsage(AttributeTargets.Method)]
public class CustomAttribute : Attribute {}
public class Foo
{
[Custom]
public void Method() {}
}
Then I query the attribute at run time
var attribute = typeof(Foo)
.GetMethod("Method")
.GetCustomAttributes(false)
.OfType<CustomAttribute>()
.First();
Can "attribute" tell it was applied to the "Method" method on the "Foo" class?
I believe not, but if it could it would not be helpful.
I'll explain.
Attributes are only created once you query for them. If you just open a dll, none of the attributes that you added will be created. You will first have to get a pointer to the object that the attributes apply to, and then, once you ask for it's attributes, the .net framework will create them for you. So by the time they are instantiated and your code gets to evaluate them you already know what they apply to.
Because of this, I believe it is reccommended to not put too much magic in the attributes themselves.
Not in a built-in fashion. If an attribute contains method logic that requires knowledge of what it's decorating, the method should take a MemberInfo parameter (or a more derived type like MethodInfo, PropertyInfo, FieldInfo etc.), or an Object if the instance should be passed directly. Then, when invoking the logic on the attribute, it can be given the instance, or the appropriate metadata class, from which it was gotten by the controlling code in the first place.

C# AttributeUsage for Specific Class

Is it possible to have something like AttributeUsage to restrict the use of an attribute to a specific class (not just AttributeTargets.Class - that would be any class)?
One way to accomplish this, if you have access to the specific class, is detailed by Marc Gravel here: http://marcgravell.blogspot.com/2009/06/restricting-attribute-usage.html. Basically you implement the attribute as a protected class of the specific type. Then it can only be used by that type.
No. There is nothing in the framework that would do this.
However, the code that uses the attribute in question could always check to make sure that the class's type is the specific class (or one of its subclasses).
Attributes, by themselves, do nothing - so this should have the same effect.
Make all data in the Attribute accessible only by a public static method which takes the class you want in question and checks to see if it has the given attribute.

Categories