
Introduction
Reflection allows you to programmatically inspect an assembly, and get information about the assembly, including all object types contained within. This information includes the attributes you have added to those types. The reflection objects reside within the System.Reflection namespace.
This demo program will inspect an assembly and display a list of all attributes defined on the assembly. The entire source code is downloadable and I will explain how it works.
Source Code Explanation
The code first checks the parameters passed to the command-line - if none are supplied, or if the user types FindAttributes /? then the Usage() method will be called, which will display a simple command usage summary:
if (args.Length == 0)
Usage();
else if((args.Length == 1)&&(args[0] == "/?"))
Usage();
Next, we reconstitute the command-line arguments into a single string. The reason for this is that it's common to have spaces in directory names, such as "Program Files", and this would be considered as two arguments by virtue of there being a space. So, we iterate through all the arguments stitching them back into a single string, and use this as the name of the assembly to load:
foreach(string arg in args)
{
if(assemblyName == null)
assemblyName = arg;
else
assemblyName = string.Format("{0} {1}", assemblyName, arg);
}
We then attempt to load the assembly, and retrieve all custom attributes defined on that assembly with the GetCustomAttributes() method:
Assembly a = Assembly.LoadFrom(assemblyName);
object[] attributes = a.GetCustomAttributes(true) ;
if(attributes.Length > 0)
{
Console.WriteLine("Assembly attributes for '{0}'...", assemblyName);
foreach(object o in attributes)
Console.WriteLine(" {0}", o.ToString());
}
Any attributes that are found are output to the console.
You can build the executable of the source code by using the command-line compiler like this:
>csc FindAttributes.cs
Running the Program
When you test the program against the FindAttributes.exe file, an attribute called DebuggableAttribute will be displayed, as shown in the screen shot. Although this attribute was not specified, it has been added by the C# compiler, and you will find that most of your executables have this attribute.
Additional Notes
You can alter the code as appropriate to add on as many assembly attributes as you wish. As an example, try modifying the source code by un-commenting the line after the using directives at the beginning of the listing.
When you recompile and run the code, you will see an additional attribute has been added to the list, the System.Reflection.AssemblyTitleAttribute.
Please check Karli Watson's Beginning Visual C# [ISBN 1-86100-758-2] by Wrox Press for more information.
| You must Sign In to use this message board. |
|
|
 |
|
 |
Great program
لقد قمت بالتصويت لك لما لا تقوم بالتصويت لى
http://www.codeproject.com/useritems/startedit.asp
Ahmad Shaban
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hi Ahmad, don't u know how i can add some custom attributes to assembly (something like AssemblyVersion but my own attributes - e.g. AssemblyAuthorICQNum )? I want to see this attribute when viewing property page (right click->properties on dll file). Thanks for ur help.
David "DNH" NoHejl
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Hi,
A custom attribute is simply a special class that must comply with these two specifications:
- A custom attribute must derive from System.Attribute - The Constructor(s) for an attribute may only contain types that can be resolved at compile time (such as strings and integers)
The restriction on the types of parameters allowable on the attribute constructor(s) is due to the way that attributes are persisted into the assembly metadata. When you use an attribute within code, you are using the attribute's constructor inline. For example: [assembly: AssemblyKeyFile("Company.Public")]
In order to create a custom attribute class, we must: - Create a class derived from System.Attribute - Create the constructor(s) and public properties as required - Attribute the class to define where it is valid to use your custom attribute
Here is an example code that may help you understand the idea:
using System;
public class TestCaseAttribute : Attribute { public TestCaseAttribute(System.Type testCase) { TestCase = testCase; }
public readonly System.Type TestCase;
public void Test() { object o = Activator.CreateInstance(TestCase); } }
The last thing we need to do is attribute your attribute class to indicate where your attribute class can be used. For the test case attribute we want to say "this attribute is only valid on classes". We can decide where an attribute that we create is valid.
Add this line just before the attribute class definition:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
Now we need an object to test with a test case:
[TestCase (typeof(TestAnObject))] public class SomeCodeOrOther { public SomeCodeOrOther() { }
Public int Do() { return 999; } }
Now we need to write a test class:
public class TestAnObject { public TestAnObject() { SomeCodeOrOther scooby = new SomeCodeOrOther();
if(scooby.Do() != 999) throw new Exception("Ooops"); } }
You can use a simple Main() function to test your custom attribute. You need only to reference the System.Reflection namespace and write the following line just before the declaration of the SomeCodeOrOther class:
[TestCaseAttribute(typeof(TestAnObject))]
I hope this is helpful
Thank you.
AYH
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi AYH, i am sorry, maybe i didn't describe my problem enough. I know how to create & use custom attribute, but i want to add my attributes to .exe or .dll files and i want them to be visible using right-click on file and showing properties dialog. On "version" tab in this dialog u can see details like company, assembly version, trademarks etc. I know that these attributes can be defined in AssemblyInfo.cs file (when using VS.NET) but simply derive my custom attribute, like
[AttributeUsage(AttributeTargets.Assembly)] public sealed class AssemblyExtra:Attribute { private string m_extraData = null; public string ExtraData { get { return m_extraData; } } public AssemblyExtra(string extraData) { this.m_extraData = extraData; }
public override string ToString() { return m_extraData; } }
When applied in AssemblyInfo.cs :
using System.Reflection; using System.Runtime.CompilerServices; using DNH.Common.Assemblies;
[assembly: AssemblyTitle("DNH.Common.Mathematica")] [assembly: AssemblyDescription("Mathematical functions")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("DNH")] [assembly: AssemblyProduct("DNH.Common Framework")] [assembly: AssemblyCopyright("(c) DNH 2003-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: AssemblyExtra("Here is something extra")]
Last information ("Here is something extra") is not accesible throught property pages like all other attributes above. Is it possible to add custom attributes of this type? It is not difficult to guess that those attributes must have at least two properties - value of attribute (like "1.4.22") and description for it (like "Assembly Version") because in property pages there is no item labeled AssemblyVersion (which is actuall name of attribute), but is has user-friendly name. But how to label them to be recognised by property page dialog? Should it be property, function or field? Who knows. I even tried to overload ToString() but it doesn't work. I hope the problem is more clear now. Anyway thank u for ur response.
DNH
|
| Sign In·View Thread·PermaLink | 2.25/5 |
|
|
|
 |
|
 |
Command line: Should paths that include spaces be enclosed in quotation marks? The current technique used does not allow for adding further command line options in the future.
Typos: modefying -> modifying BSc. -> B.Sc. He Also -> He also governamental -> governamental consultency -> consultancy
phpWebNotes is a page annotation system modelled after php.net. http://webnotes.sourceforge.net/demo.php[^]
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|