I have a class where I define one constant from another class would read these constants or the content of attributes and properties of the class . Something like read the metadata of the class.
something like this:
namespace Ventanas._01Generales
{
class Gral_Constantes
{
public class Cat_Productos
{
public const String Tabla_Productos = "Cat_Productos";
public const String Campo_Producto_ID = "Producto_ID";
}
public class Cat_Grupos_Productos
{
public const String Tabla_Grupos_Productos = "Cat_Grupos_Productos";
public const String Campo_Grupo_Producto_ID = "Grupo_Producto_ID";
}
}
}
in other class for example some like this
namespace Ventanas._01Generales
{
class Pinta_Ventana
{
public void Crea_Insert()
{
foreach(Properties p in Cat_Producto.Properties)
{
miControl.Text = p.value; //show "Cat_Grupos_Productos"
miControl.Name = p.value; //show Tabla_Grupos_Productos
}
}
}
}
You need Type.GetProperties (MSDN) This code will work:
foreach (PropertyInfo p in typeof(Cat_Producto).GetProperties())
{
...
}
Now a few caveats:
You are using reflection which is really slow, and the fact that you are using it indicates you are likely doing something terribly wrong.
If you output the way your sample code does, only the last property's information will be visible, since you never let the UI update.
Your code doesn't actually have properties, they have const fields, so this code wouldn't return any of them. Make them properties for this method to work. You can use Type.GetFields if you want the fields version.
It looks like you want to use the System.Reflection namespace. If you are interested in getting the names of the public const strings, you will need to use MemberInfo. This should get you started:
MemberInfo[] members = typeof(MyClass).GetMembers();
foreach(MemberInfo m in members)
{
//do something with m.Name
Console.WriteLine(m.Name);
}
Related
I would like to store static variable in single class and use it in different classes.
What is the best practice in C#?
JavaScript example.
Just for example. I am looking for something like this:
I have single file MyStaticDataObject.js with one or more static variables.
const MyStaticDataObject = {
someKey: someValue,
anotherKey: anotherValue,
//...
}
export { MyStaticDataObject };
and I can use them in any other file:
import { MyStaticDataObject } from "./MyStaticDataObject.js";
// ... somewhere in code
console.log(`Value of someKey:`, MyStaticDataObject["someKey"]);
namespace nm1 {
internal class MyStaticDataObject {
public const string Key1 = "Value1";
public const string Key2 = "Value2";
}
}
In other classes (outside the namespace), reference the namespace using nm1; and use it. Otherwise they can be used directly without the using
using nm1;
internal class TestClass
{
private string Key1 = MyStaticDataObject.Key1;
}
Maybe late.
But this is a better way - if you need use these constants value frequently.
Declare a class with some constants.
public class ConstantsClass
{
public const string ConstName1 = "ConstValue1";
public const string ConstName2 = "ConstValue2";
public const string ConstName3 = "ConstValue3";
}
Using this class in static in code file you want. (C# 6.0 feature)
using static ConstantsClass;
namespace YourNamespace
{...
Use the constanst in the way same as it declared in local.
CallMethod(ConstName1);
I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.
Is it possible to get value without creating an instance ?
I have this class:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
Now I need get the value "David", without creating instance of MyClass.
Real answer: no. It's an instance property, so you can only call it on an instance. You should either create an instance, or make the property static as shown in other answers.
See MSDN for more information about the difference between static and instance members.
Tongue-in-cheek but still correct answer:
Is it possible to get value without creating an instance ?
Yes, but only via some really horrible code which creates some IL passing in null as this (which you don't use in your property), using a DynamicMethod. Sample code:
// Jon Skeet explicitly disclaims any association with this horrible code.
// THIS CODE IS FOR FUN ONLY. USING IT WILL INCUR WAILING AND GNASHING OF TEETH.
using System;
using System.Reflection.Emit;
public class MyClass
{
public string Name { get{ return "David"; } }
}
class Test
{
static void Main()
{
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var dynamicMethod = new DynamicMethod("Ugly", typeof(string),
Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var ugly = (Func<string>) dynamicMethod.CreateDelegate(
typeof(Func<string>));
Console.WriteLine(ugly());
}
}
Please don't do this. Ever. It's ghastly. It should be trampled on, cut up into little bits, set on fire, then cut up again. Fun though, isn't it? ;)
This works because it's using call instead of callvirt. Normally the C# compiler would use a callvirt call even if it's not calling a virtual member because that gets null reference checking "for free" (as far as the IL stream is concerned). A non-virtual call like this doesn't check for nullity first, it just invokes the member. If you checked this within the property call, you'd find it's null.
EDIT: As noted by Chris Sinclair, you can do it more simply using an open delegate instance:
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var openDelegate = (Func<MyClass, string>) Delegate.CreateDelegate
(typeof(Func<MyClass, string>), method);
Console.WriteLine(openDelegate(null));
(But again, please don't!)
You can make that property static
public static string Name{ get{ return "David"; } }
Usage:
MyClass.Name;
You requirements do seem strange, but I think you're looking for some kind of metadata. You can use an attribute to achieve this:
public class NameAttribute : Attribute {
public string Name { get; private set; }
public NameAttribute(string name) {
Name = name;
}
}
[Name("George")]
public class Dad {
public string Name {
get {
return NameGetter.For(this.GetType());
}
}
}
[Name("Frank")]
public class Son : Dad {
}
public static class NameGetter {
public static string For<T>() {
return For(typeof(T));
}
public static string For(Type type) {
// add error checking ...
return ((NameAttribute)type.GetCustomAttributes(typeof(NameAttribute), false)[0]).Name;
}
}
Now this code can get names with and without instances:
Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());
You can make your property static, as pointed out by many others.
public static string Name{ get{ return "David"; } }
Be aware that this means your instances of MyClass will no longer have their own Name property, since static members belong to the class, not the individual object instances of it.
Edit:
In a note, you mentioned that you want to override the Name property in subclasses. At the same time, you want to be able to access it at the class level (access it without creating an instance of your class).
For the static properties, you would simply create a new Name property in each class. Since they are static, you're always (almost always, yay reflection) going to access them using a specific class, so you'd be specifying which version of Name you want to get. If you want to try and hack polymorphism in there and get the name from any given subclass of MyClass, you could do so using reflection, but I wouldn't recommend doing so.
Using the example from your comment:
public class Dad
{
public static string Name { get { return "George"; }
}
public class Son : Dad
{
public static string Name { get{ return "Frank"; }
}
public static void Test()
{
Console.WriteLine(Dad.Name); // prints "George"
Console.WriteLine(Son.Name); // prints "Frank"
Dad actuallyASon = new Son();
PropertyInfo nameProp = actuallyASon.GetType().GetProperty("Name");
Console.WriteLine(nameProp.GetValue(actuallyASon, null)); // prints "Frank"
}
As a side note, since you are declaring a property that has only a getter and it is returning a constant value, I recommend possibly using a const or static readonly variable instead.
public const string Name = "David";
public static readonly string Name = "David";
Usage for both would be the same:
string name = MyClass.Name;
The main benefit (and drawback) of const is that all references to it are actually replaced by its value when the code is compiled. That means it will be a little faster, but if you ever change its value, you will need to recompile ALL code that references it.
Whenever you write C# code, always check if your method and property getter/setter code does anything at all with other instance members of the class. If they don't, be sure to apply the static keyword. Certainly the case here, it trivially solves your problem.
The reason I really post to this question is that there's a bit of language bias at work in some of the answers. The C# rule that you can't call an instance method on a null object is a specific C# language rule. It is without a doubt a very wise one, it really helps to troubleshoot NullReferenceExceptions, they are raised at the call site instead of somewhere inside of a method where it gets very hard to diagnose that the this reference is null.
But this is certainly not a requirement to the CLR, nor of every language that run on the CLR. In fact, even C# doesn't enforce it consistently, you can readily bypass it in an extension method:
public static class Extensions {
public static bool IsNullOrEmpty(this string obj) {
return obj != null && obj.Length > 0;
}
}
...
string s = null;
bool empty = s.IsNullOrEmpty(); // Fine
And using your property from a language that doesn't have the same rule works fine as well. Like C++/CLI:
#include "stdafx.h"
using namespace System;
using namespace ClassLibrary1; // Add reference
int main(array<System::String ^> ^args)
{
MyClass^ obj = nullptr;
String^ name = obj->Name; // Fine
Console::WriteLine(name);
return 0;
}
Create a static property:
public class MyClass
{
public static string Name { get { return "David"; } }
public MyClass()
{
}
}
Get it like so:
string name1 = MyClass.Name;
That is not possible. As Name is an instance property, you can only get its value if you have an instance.
Also, note that you are not talking about a parameter, but about a property.
Create a static class or a static property, and you don't have to explicitly instantiate it.
I am wanting to access the custom attributes on a Field in the class. I want to access the attributes placed on the field during the fields constructor. Is this possible?
Edit 06/28/09
Something like the below pseudo code
class SpecialInt
{
int _intVal;
int _maxVal;
public SpecialInt()
{
//Get attribute for the instantiated specialint
_maxVal = GetAttribute("MaxValue")
}
}
class main()
{
[MaxValue(100)]
SpecialInt sInt;
public main()
{
sInt = new SpecialInt()
}
}
Sure this is possible. Attributes are stored in Metadata and this is easily accessible during construction of an object.
public class Foo {
[Something]
public int Field1;
public Foo() {
FieldInfo fi = typeof(Foo).GetField("Field1");
SomethingAttribute si = (SomethingAttribute)fi.GetCustomAttribute(typeof(SomethingAttribute),false)[0];
// grab any Custom attribute off of Fiield1 here
}
}
You can test them from anywhere. Attributes are inserted into the metadata for the type when you compile it. A type doesn't need to be instantiated to access field properties.
I have a lot of constant string values in my application which I want to have as strongly typed objects in C# for code reuse and readability. I would like to be able to reference the string value like so:
Category.MyCategory //returns a string value ie “My Category”
Category.MyCategory.Type.Private //returns a string value ie “private”
Category.MyCategory.Type.Shared //returns a string value ie “shared”
I have started by implementing the following classes each containing a list of public string valued fields with a public property which exposes the child.
Category, MyCategory, Type
However I already know this is not the way to go so could do with a bit of advice on this one.
An example of this is where I am using the Syndication classes to add a category to an atom feed. I am creating the items in this feed dynamically so need to use the notation as shown.
item.Categories.Add( new SyndicationCategory
{
Scheme = Category.PersonType,
Label="My Category",
Name=Category.MyCategory.Type.Private
});
Keep your string constants close to where you need them, IMO having a class that just declares constants is an OO antipattern
Why not simply implement them as classes with overridden ToString implementations?
public class MyCategory
{
private readonly MyType type;
public MyCategory()
{
this.type = new MyType();
}
public MyType Type
{
get { return this.type; }
}
// etc.
public override string ToString()
{
return "My Category";
}
}
public class MyType
{
public override string ToString()
{
return "My Type";
}
// more properties here...
}
However, for general purposes, consider whether the strings in themselves don't represent concepts that are better modeled as full-blown objects.
I completely agree with Rob. If you still want to have a "bag of strings", you could try using nested classes, something like below. I don't really like it, but it works.
public class Category
{
public class MyCategory
{
public const string Name = "My Category";
public class Type
{
public const string Private = "private";
public const string Shared = "shared";
}
}
}