Why does my .NET Attribute not perform an action? - c#

I've created a simple Attribute:
[AttributeUsage(AttributeTargets.Method)]
public class InitAttribute : System.Attribute
{
public InitAttribute()
{
Console.WriteLine("Works!");
}
}
and I apply it to a simple method:
static class Logger
{
public static string _severity;
public static void Init(string severity)
{
_severity = severity;
}
[Init()]
public static void p()
{
Console.WriteLine(_severity);
}
}
What is going on is pretty streight-forward. Only, I expect the attribute to perform an action (printing Works!), but this does not happen.
Addictionally, printing "Works!" is of course just for debugging purposes: I'd like to access the instance's property _severity (to check if is != null, for example), but everything I keep reading about attributes (that are pretty new to me) is about accessing the class' methods or properties and so on via reflection. Once I've evaluated _severity, how can I modify the behavior of the decorated method (in this case, rise an exception "Logger is not initialized" and do not execute it)?
Any help appreciated.

If you need to perform an action as control enters a method, you should look at aspect-oriented programming and frameworks such as PostSharp. Attributes are not designed to perform anything by themselves. They are just a bunch of data (or metadata if you will) attached to stuff in IL assemblies that can be queried at runtime.

Attributes only allow decoration of types and members, but the attribute itself cannot acces the decorated object. You will have to use the constructor parameters of the attribute to pass in any data you require to work with within the attribute.
If you wish to use attributes to automatically alter the behaviour of their target objects, you will have to look at AOP solutions like PostSharp.

The attribute is never actually instantiated and so its constructor is never called. The attribute remains as meta-data until you use reflection to retrieve it. As has been mentioned previously what you are after is an Aspect Oriented Programming tool. PostSharp works by altering the assembly as a post-build step. If you are using the Castle Windsor or Unity Inversion of Control Containers they both offer AOP capabilities as well.

Related

How can i use custom attribute my c# project

i want use custom attribute on my n-tier project. for
-Caching-
-Logging
-Validation
-Exception
First of all you should search for AOP. this is some kind of developing methodology
Aspect-Oriented Programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. Wikipedia
It is not as simple as you think,in C# you have to use some 3rd party Library.
I suggest to start with MrAdvice, it will helps you.
Writing your custom attributes would look a little something like this:
using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method)]
public class LogAttribute : Attribute
{
public bool _loggingEnabled;
public LogAttribute(loggingEnabled)
{
_loggingEnabled = loggingEnabled;
}
}
Usage example:
[Log(true)]
public class SampleClass
{
}
If you require further clarification if you share a little bit more about your intended usage of the attributes I'd be able to clarify a bit more. For instance, I'm not sure if you wanted your logging attribute to give you a means to explicitly state if that class/struct would be logged, but that's how I decided to demonstrate this. Also, note you can apply that to properties, and various other members via the AttributeUsage attribute on your attribute class declaration. I hope that helps.
Update:
Save method example:
[Log(true)]
public void Save(Company company)
{
_context.Save();
}
Then you'll use the static method Attribute.GetCustomAttribute(MemberInfo element, Type attributeType) to retrieve information stored in that attribute. Since in this case, you'll likely want to use logging in many places you'd write another method (most likely static as well) somewhere else in your application that'd look something like this (see the link to the System.Reflection reference below for more information).
public static void Log(MemberInfo element)
{
LogAttribute attribute = Attribute.GetCustomAttribute(element, typeof(LogAttribute);
if (attribute._loggingEnabled)
{
// Create log file and add information from here.
}
}
Attribute Reference
Reflection Reference

Can an Attribute be used to prevent a method from being called?

I'm trying to write a custom attribute that I can apply to methods that will prevent the method from being called when Transaction.Current is null. I currently have a basic attribute class that throws an exception if that item is null. Here it is:
[AttributeUsage(AttributeTargets.Method)]
public class RequiresTransactionAttribute : System.Attribute
{
public RequiresTransactionAttribute()
{
if (Transaction.Current == null)
{
throw new Exception("requires transaction");
}
}
}
The problem is that this does not cause method calls to fail in my tests.
I've read that these attributes are converted to meta data and so this constructor is never executed because it's optimized out unless I specifically use reflection to cause the attribute to be executed.
Is it possible to prevent a method from being called based on such a requirement as mine using attribute approach, or perhaps some other better method?
With very few exceptions (attributes with inbuilt behaviour by the runtime, where the JIT is looking for them - like [MethodImpl(...)] or code-access-security attributes), attributes are completely inert - they exist purely as metadata. They aren't even instantiated as objects unless you use reflection to ask it to do so.
So no: you can't influence runtime behaviour like this unless you are using a framework that goes out of the way to look for attributes, instantiate them, and treat them as runnable code via methods that the framework itself checks. ASP.NET MVC would be an example of a framework that does this.
The other option is an IL rewriter such as post-sharp, where attributes are a popular hook for injecting additional code during weave.

How to add an attribute on a method that kicks off when the method is called?

I have a pretty standard .net core 2 WebApi project. I want to add an attribute on a method that will kick off when the action is called.
In the pseudo code below whenever someone posts to the foo action, I'd like to log the body of the POST. To that end I add the [LogBody] attribute. But I don't know how to actually kick off a method in the attribute.
class SomeController: Controller {
[HttpPost]
[LogBody]
public void foo([FromBody] SomeObj obj) {
return View(obj);
}
}
class LogBodyAttribute: Attribute {
void LogIt() {
string methodName = getMethodName();
string body = new StreamReader(Request.Body, Encoding.UTF8).ReadToEnd();
SaveData(methodName, body);
}
}
P.S. I know I can do this with PostSharp, but I'd rather not.
It can be done, but it's not easy - and the immediate answer to your question involves reflection and code injection stuff. Here is an SO question that might help you do what you want: C# Attribute to trigger an event on invoking a method
The attributes provide a static meta-data that is included into the compiled code. This information can be queried at run-time and used to perform logic; however, the attribute by itself cannot trigger an action.
Given an object, you can get the attribute like this:
Type type = controller.GetType();
var myAttribute = type
.GetMethod(methodName)
.GetCustomAttributes(true)
.OfType<MyAttribute>()
.FirstOrDefault();
The Boolean argument to GetCustomAttributes indicates whether inherited attributes must be returned.
Maybe what you are looking for is Aspect-oriented programming AOP. This allows you to inject code into methods and properties in a post compilation process. Attributes can be used to include or exclude methods. There are different AOP products available for C#.
Yet another approach is to use the Decorator pattern. A decorator is a wrapper class providing the same API than the wrapped class and allows to add behavior to the methods and properties of the wrappee. Used together with an inversion of control (IoC) Container or with the Factory method pattern, behavior can automatically be injected.

Is there a way to apply an attribute to a method that executes first?

Without using a library like PostSharp, is there a way to set up a custom attribute that I can have logic in that when attached to a method, will execute PRIOR to entering that method?
No; attributed are not intended to inject code. Tools like postsharp get around that with smoke and mirrors, but without that: no. Another option might be a decorator pattern,
perhaps dynamically implementing an interface (not trivial by any means). However, adding a utility method-call to the top of the method(s) is much simpler, and presumably fine since if you have access to add attributes you have access to add a method-call.
Or put another way: tools like postsharp exist precicely because this doesn't exist out-of-the-box.
// poor man's aspect oriented programming
public void Foo() {
SomeUtility.DoSomething();
// real code
}
In some cases, subclassing may be useful, especially if the subclass is done at runtime (meta-programming):
class YouWriteThisAtRuntimeWithTypeBuilder : YourType {
public override void Foo() {
SomeUtility.DoSomething();
base.Foo();
}
}

Attributes creating fields in C#

Alright, so after a few hours of me playing around to no avail, I built a model:
[AttributeUsage(AttributeTargets.All)]
public class PublicAttribute : System.Attribute
{
public enum Access { Public, Private }
public PublicAttribute(string Name, Access acs)
{
}
public PublicAttribute(string Name, Access acs, Action get, Action set)
{
}
}
So that if somebody were to do something like this:
[Public("PublicProperty", PublicAttribute.Access.Public)]
private string PrivateProperty = "hello";
or
[Public("PublicProperty", PublicAttribute.Access.Public, ()=>{return PrivateProperty;}, ()=>{PrivateProperty = value})]
private string PrivateProperty = "hello";
and then if somebody was trying to access PrivateProperty, they could just go:
ContainingClass.PublicProperty = //ect
"PublicProperty". and that is because of the attribute, and it would use those get/set accessors.
What I'd like to know:
Is this even possible?
Is there something that already does this?
If its possible, (even if there is something else) How do i do this?
Basically no to all 3, as C# is a strongly typed language. Even with duck typing what you're trying to achieve doesn't fit the language.
The attributes you've written allow you to interrogate the properties that have those attributes in the class, but you still need to use Reflection to discover which properties of the attribute class are set. The syntax you want to use is checked at compile-time.
No, this is not possible using attributes. Properties are part of the class metadata emitted by the C# compiler, and the C# compiler does not consider custom attributes.
You may be able to do this by using a post-processor such as PostSharp, which can rewrite your assembly after the fact, and can be instructed to consider custom attributes. However, you still wouldn't be able to include a delegate in the attribute: the set of types that can be stored in attribute state is extremely limited.
Microsoft made the WebMethodAttribute in a way reminiscent of what you're trying to describe making it represent more permission than C# public, effectively making a method available outside the application domain to the entire Internet (a very global scope). You might read it to get real implementation insight and ideas.
But you're hitting it very simply. You'll have to program some infrastructure to make it work. It's not automatic and you don't have access to Microsoft's source code for all the details.

Categories

Resources