Whenever the TestAttribute attribute is called on a class, I would like to add that type to a list. How can I do that?
Example:
using System;
using System.Collections.Generic;
[AttributeUsage(AttributeTargets.Class)]
public class TestAttribute : Attribute {
public TestAttribute() {
// Add type to list
}
}
public static class TypeHolder {
public static List<Type> Types = new List<Type>();
}
[Test]
public static class MainClass {
public static void Main(string[] args) {
Console.WriteLine(TypeHolder.Types.Count);
}
}
Related
I have below code but not able to validate the type of displayPage.
using System;
public class Page{}
public class ContentPage: Page{}
public class BaseViewModel{}
public class ChildViewModel : BaseViewModel {}
public class Base<T> : ContentPage where T:BaseViewModel{
public void Method(){
Console.WriteLine("in Base=>Method");
}}
public class ChildPage : Base<ChildViewModel> {}
public class Program{
public static void Main(){
Page displayPage = new ChildPage();
Console.WriteLine(displayPage is Base<BaseViewModel>);
if(displayPage is Base<BaseViewModal>) **-> Its returning false** {
(displayPage as Base<BaseViewModel>).Method();
}}}
If you are in generic class like FormBase<T>, then you case just :
public class FormBase<T> where T: BaseViewModel
{
public void Display(Page displayPage)
{
(displayPage as Base<T>).Method();
}
}
Else, you need use covariance on the generic type. But it's possible only with delegate and interface. To do this, you need to add a interface like :
using System;
public class Page { }
public class ContentPage : Page { }
public class BaseViewModel { }
public interface IBase<out T> where T : BaseViewModel
{
void Method();
}
public class Base<T> : ContentPage, IBase<T> where T : BaseViewModel
{
public void Method()
{
Console.WriteLine("in Base=>Method");
}
}
public class Program
{
public static void Main()
{
Page displayPage = new Base<BaseViewModel>();
(displayPage as IBase<BaseViewModel>).Method();
}
}
In the declaration interface interface IBase<out T>, the keyword out enable the covariance for the generic type.
More information in the documentation :
Covariance and contravariance in generics
You need to pass the type along with Base class name
(displayPage as Base<BaseViewModel>).Method();
Pseudo code
using System;
public class Page
{
}
public class ContentPage: Page
{
}
public class BaseViewModel
{
}
public class Base<T> : ContentPage where T:BaseViewModel
{
public void Method()
{
Console.WriteLine("in Base=>Method");
}
}
public class Program
{
public static void Main()
{
Page displayPage = new Base<BaseViewModel>();
(displayPage as Base<BaseViewModel>).Method();
}
}
here is fiddle: https://dotnetfiddle.net/hiAPmq
Lets say i have the following attribute class.
//Attribute Implementation
public abstract class TestAttribute : Attribute
{
public abstract void UpdateSomething(string s);
}
public class CustomAttTest : TestAttribute
{
private State state;
public CustomAttTest(State state)
{
this.state = state;
}
public override void UpdateSomething(string s)
{
if (state.Equals(State.First))
{
Console.WriteLine("First State!! " + s);
}
}
}
public enum State
{
First, Second, Third
}
How can i call the Updatesomthing function inside the attribute class?
following is the attribute implementation example.
public abstract class Vehicle
{
//Coode
}
[CustomAttTest(State.First)]
public class Ferrari : Vehicle
{
//Code
}
Here is the full code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
var foo = new Ferrari();
//How do i call the UpdateSomething implemented insde the CustomAttTest attribute class?
}
}
public abstract class Vehicle
{
//Coode
}
[CustomAttTest(State.First)]
public class Ferrari : Vehicle
{
//Code
}
//Attribute Implementation
public abstract class TestAttribute : Attribute
{
public abstract void UpdateSomething(string s);
}
public class CustomAttTest : TestAttribute
{
private State state;
public CustomAttTest(State state)
{
this.state = state;
}
public override void UpdateSomething(string s)
{
if (state.Equals(State.First))
{
Console.WriteLine("First State!! " + s);
}
}
}
public enum State
{
First, Second, Third
}
}
You need to use reflection:
foo.GetType().GetCustomAttribute<CustomAttTest>().UpdateSomething(...);
However, you should probably use an abstract method or property instead of an attribute.
I have a sample program where I have a class called ObserverTest where I have two methods
one for subscription and one for notify for any type T but I get some build errors.
Following is my sample code>
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ObserverTest obs = ObserverTest.Instance();
obs.SubscribeToChange<int>(GotChange);
obs.NotifyChange<int>(200);
Console.ReadLine();
}
private static void GotChange(int val)
{
Console.WriteLine(string.Format("Changed value is {0}", val));
}
}
public class ObserverTest
{
private static ObserverTest _obsTest;
private Action<T> _observer;
private ObserverTest()
{
}
public static ObserverTest Instance()
{
return _obsTest = _obsTest == null ? new ObserverTest() : _obsTest;
}
public void NotifyChange<T>(T val)
{
_observer(val);
}
public void SubscribeToChange<T>(Action<T> observer)
{
_observer = observer;
}
}
}
and followings are the errors:
Error 1 The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?) C:\Users\Administrator\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs 24 22 ConsoleApplication1
Error 2 The field 'ConsoleApplication1.ObserverTest._observer' cannot be used with type arguments C:\Users\Administrator\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs 37 10 ConsoleApplication1
Can anyone please help me in removing the errors ?
Thanks in advance.
Try to add generic in the class definition:
public class ObserverTest<T>
complete code:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ObserverTest<int> obs = ObserverTest<int>.Instance();
obs.SubscribeToChange<int>(GotChange);
obs.NotifyChange<int>(200);
Console.ReadLine();
}
private static void GotChange(int val)
{
Console.WriteLine(string.Format("Changed value is {0}", val));
}
}
public class ObserverTest<T>
{
private static ObserverTest<T> _obsTest;
private Action<T> _observer;
private ObserverTest()
{
}
public static ObserverTest<T> Instance()
{
return _obsTest = _obsTest == null ? new ObserverTest<T>() : _obsTest;
}
public void NotifyChange<E>(T val)
{
_observer(val);
}
public void SubscribeToChange<E>(Action<T> observer)
{
_observer = observer;
}
}
}
If you have a member that's a generic, like _observer, you need to put a type argument on the ObserverTest class, like so:
public class ObserverTest<T> {
}
Of course, you'll need to modify your Instance method as well.
The problem you are having is that you are declaring a field member that has a generic type and the class does not:
public class ObserverTest
{
private static ObserverTest _obsTest;
private Action<T> _observer;
...
}
So when you try to create an instance of the ObserverTest class, it tries to setup the field members and runs into the problem of not knowing what concrete type _observer is.
To fix this you'll have to define the class with a generic parameter and any calls that instantiate the class:
public class ObserverTest<T>
{
private static ObserverTest _obsTest;
private Action<T> _observer;
public static ObserverTest<T> Instance<T>()
{
...
}
...
}
I know I can put my enum at the Namespace area of a class so everyone can access it being in the same namespace.
// defined in class2
public enum Mode { Selected, New, }
What I want is to access this enum from
public class1
{
var class2 = new class2();
// Set the Mode
class2.Mode = Model.Selected
}
Is this somehow possible without using namespace area?
You can declare an enum outside of a class:
namespace MyNamespace
{
public enum MyEnum
{
Entry1,
Entry2,
}
}
And then you can add using MyNamespace; where it needs to be used.
Aaron's answer is very nice but I believe there is a much better way to do this:
public static class class1
{
public void Run()
{
class2.Mode mode = class2.Mode.Selected;
if (mode == class2.Mode.Selected)
{
// Do something crazy here...
}
}
}
public static class class2
{
public enum Mode
{
Selected,
New
}
}
No point over complicating this. It is a simple task.
All the Best
Chris.
If you are trying to do what is described below it will not work...
public class MyClass1
{
private enum Mode { New, Selected };
public Mode ModeProperty { get; set; }
}
public class MyClass2
{
public MyClass2()
{
var myClass1 = new MyClass1();
//this will not work due to protection level
myClass1.ModeProperty = MyClass1.Mode.
}
}
What you could do however is below, which will work...
public interface IEnums
{
public enum Mode { New, Selected };
}
public class MyClass1
{
public IEnums.Mode ModeProperty { get; set; }
}
public class MyClass2
{
public MyClass2()
{
var myClass1 = new MyClass1();
//this will work
myClass1.ModeProperty = IEnums.Mode.New;
}
}
Yes:
class2.Mode = class2.Mode.Selected
But note that you can't have a nested type defined that has the same name as one of the outer class' members, so this code will not compile. Either the enum or the property will need to be named something else. Your class name and variable name conflict too, making this a bit more complex.
To make this a more generic answer, if you have this:
public class Foo
{
public SomeEnum SomeProperty { get; set; }
public enum SomeEnum {
Hello, World
}
}
Then this code will assign an enum value to the property:
Foo foo = new Foo();
foo.SomeProperty = Foo.SomeEnum.Hello;
I ended up solving my issue by changing it to a namespace accessor, found by utilizing Intellisense. I thought the enum was in the class, not just the namespace. If it was in the class, I would recommend moving it out of the class.
namespace ABC.XYZ.Contracts
{
public class ChangeOrder : BaseEntity, IAuditable
{
...
}
public enum ContractorSignatureType
{
A,
B,
V
}
}
ContractorSignatureType = Contracts.ContractorSignatureType.B,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace #enum
{
class temp
{
public enum names
{
mohitt,
keval,
Harshal,
nikk
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)temp.names.nikk);
Console.ReadKey();
}
}
}
//by using this you can access the value of enum.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace #enum
{
class temp
{
public enum names
{
mohitt,
keval,
Harshal,
nikk
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(temp.names.nikk);
Console.ReadKey();
}
}
}
When the only code in there is for a class how would you code it adding public to the default class like so
namespace HW2_2_Spaceship
{
public class Spaceship //added public to the default class
{
static void Main(string[] args)
{
}
or
namespace HW2_1_Book
{
class Book
{
static void Main(string[] args)
{
}
public class Book // added a new class with in the default class
{
In general, each class should have their own file.
Main should be in Program.cs
There are usecases where you can use Inner classes, see Using Inner classes in C#.
//Program.cs, if u use visual studio then ensure you add
// the public access modifier yourself
namespace HW2_2_Spaceship
{
public class Program
{
public static void Main(string[] args)
{
//Do something here
}
}
}
//Book.cs, add the public modifier to the class
namespace HW2_2_Spaceship
{
public class Book
{
//add method and properties here
}
}