This question already has answers here:
How to get a property value using reflection
(2 answers)
Closed 8 years ago.
I'm trying to create a simple generic function:
public T GetPost<T>(HttpListenerRequest request) where T : new()
{
Stream body = request.InputStream;
Encoding encoding = request.ContentEncoding;
StreamReader reader = new StreamReader(body, encoding);
string data = reader.ReadToEnd();
body.Close();
reader.Close();
// NullRefferenceException on this line:
typeof(T).GetField("Name").SetValue(null, "djasldj");
return //yet to come
}
Strangely the line with typeof(T) return this error:
Object reference not set to an instance of an object.
What is a NullReferenceException, and how do I fix it?
Also how can I return the constructed T class?
This is how I call the function:
string data = GetPost<User>(ctx.Request);
And this is the User class:
public static string Name { get; set; }
public string Password { get; set; }
The problem with your code is that you look for a field, but your T has an automatic property.
You thus need to call:
typeof(T).GetProperty("Name").SetValue(null, "djasldj");
This code for instance (stripped unnecessary code) works:
class Foo {
public static string Name { get; set; }
public string Password { get; set; }
}
class Program
{
static void Main()
{
Console.WriteLine(Foo.Name);
GetPost<Foo>();
Console.WriteLine(Foo.Name);
}
public static void GetPost<T>() where T : new() {
typeof(T).GetProperty("Name").SetValue(null, "djasldj");
}
}
I'm afraid you're trying to set property of T. But T is only a type you pass to the generic method. You've constrained it with new(), so as far as I know T type should provide parameterless constructor.
Let's say you call it GetPost<User>(request);
It should return user with some properties set. Take a look on that example (User class is as you wrote)...
This is a class with generic method:
namespace ConsoleApplication1
{
class Class1
{
public T GetPost<T>(string s) where T : new()
{
if (typeof(T)== typeof(User))
{
var result = new User();
result.Password = "some";
return (T)(object)result;
}
else
{
throw new ArgumentException();
}
}
}
}
And this is usage
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var c = new Class1();
var obj = c.GetPost<User>("dsjkd");
}
}
}
After execution variable "obj" is User object with password field set.
EDIT:
I've just seen CommuSoft post. It's better solution I think, but I'm not deleting my answer, maybe someone will find it useful.
Related
I am trying to print two methods that i have created but i cant figure out how to do it.
My project consists of Language.cs file in addition to Program.cs
This method in Language.cs:
public static void PrettyPrintAll(IEnumerable<Language> langs)
{
foreach (var printsAll in langs)
{
Console.WriteLine(printsAll.Prettify());
}
}
Prints out this method that is also in Language.cs:
public string Prettify()
{
return $"{Year}, {Name}, {ChiefDeveloper}, {Predecessors}";
}
this method prints out every query result (is also in Language.cs):
public static void PrintAll(IEnumerable<Object> sequence)
{
foreach (var prints in sequence)
{
Console.WriteLine(prints);
}
}
Language class code other than the methods above:
namespace ProgrammingLanguages
{
public class Language
{
public static Language FromTsv(string tsvLine)
{
string[] values = tsvLine.Split('\t');
Language lang = new Language(
Convert.ToInt32(values[0]),
Convert.ToString(values[1]),
Convert.ToString(values[2]),
Convert.ToString(values[3]));
return lang;
}
public int Year
{ get; set; }
public string Name
{ get; set; }
public string ChiefDeveloper
{ get; set; }
public string Predecessors
{ get; set; }
public Language(int year, string name, string chiefDeveloper, string predecessors)
{
Year = year;
Name = name;
ChiefDeveloper = chiefDeveloper;
Predecessors = predecessors;
}
All the methods are within the Language.cs file.
My issue is that i do not understand how to print them, i have tried in many ways but always get an error code The name 'PrintAll' does not exist in the current context or something like that.
In main this is how i have tried to call the method PrintAll:
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year}
{languagePrint.Name} {languagePrint.ChiefDeveloper}");
PrintAll(stringLanguage);
The static method PrintAll() belongs to the class Language and calling it from another class requier to prepend the class name first, such as Language.PrintAll()
public static void Main()
{
// some code ...
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year} {languagePrint.Name} {languagePrint.ChiefDeveloper}");
// PrintAll(stringLanguage); <-- This won't work because there is no method PrintAll() in the current class
// This now refers to the correct class where the method belongs
Language.PrintAll(stringLanguage);
}
Another way to do that would be to include the static part of the class Language in the class where Main is (I assume the class Program) :
// replace namespace by the correct namespace of the class
using static namespace.Language;
class Program
{
public static void Main()
{
// some code ...
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year} {languagePrint.Name} {languagePrint.ChiefDeveloper}");
// This now works because the static parts were imported
PrintAll(stringLanguage);
}
}
However, I discourage using this, because this may lead to confusion
I'm currently having trouble and I have no clue how to fix it.
I have 2 classes:
class A
{
public string MyParam { get; set; }
}
class B : A
{
public new string MyParam { get { return base.MyParam != null ? base.MyParam.Substring(1) : null; } }
}
When I try to access the B.MyParam it works when I have a the correct type, but in most of my methods I have a generic type
with :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class A
{
public string MyParam { get; set; }
}
public class B : A
{
public new string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
public static void MyMethod<T>(T variable) where T : A
{
Console.WriteLine(variable.MyParam);//this print hello
Console.WriteLine((variable as B).MyParam);//this print ello (exactly what i want)
Console.WriteLine(typeof(T)); // this print ConsoleApplication1.Program+A
Console.WriteLine(variable.GetType()); // this print ConsoleApplication1.Program+B
// so i need something like that
Console.WriteLine((variable as variable.GetType()).MyParam); // this line is invalid
}
static void Main(string[] args)
{
A a = new B();
a.MyParam = "Hello";
Console.WriteLine(a.GetType());
MyMethod(a);
Console.ReadKey();
}
}
}
Is there a way to do it?
Thank you in advance.
EDIT: it seems that what i want is :
dynamic variable2 = Convert.ChangeType(variable, variable.GetType());
Console.WriteLine(variable2.MyParam);
Your code doesn´t make any sense. If A inherits from B you´ll need A to override the base-implementation for your property. So I´ll assume you should rethink your inheritance-chain.
You can use override for this. Thus when your variable-parameter is of your base-class (I renamed that to A) you´re calling the base-method, if it´s a derived instance (here B) you´re calling the override:
class A
{
public virtual string MyParam { get; }
}
class B : A // note here that B derives from A, not the other way round
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; },
set { ... }
}
}
EDIT: While new intrduces a new member which (accidentally) has the same name (and signature) as the base-member it effectivly hides the base-member. Thus you effectivly have two members. Your only way to indicate which member should be used is by casting your instance to the desired class from which you need the implementation. However this somehow breaks the purpose of generics as the generic member has to know the exact types that are possible for the type-parameter.
Anyway this seems like broken design to me, as you´re actually creating a new member which has another meaning. So you should also give it a new name.
Based on your generic method, I think all you need is an interface.
public interface IMyParam
{
string MyParam { get; set; }
}
Your classes.
class A : IMyParam
{
public virtual string MyParam { get; set; }
}
class B : A
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
And your method, won't need to be generic.
public void MyMethod(IMyParam variable)
{
// Your logic here, for example.
Console.WriteLine(variable.MyParam);
}
Calling your method.
A a = new A();
a.MyParam = "Hello";
B b = new B();
b.MyParam = "Hello";
A ab = new B();
ab.MyParam = "Hello";
MyMethod(a); // Prints Hello
MyMethod(b); // Prints ello
MyMethod(ab); // Prints ello
public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.
I've a function QMain() whose return type is object.
public class QMain
{
public object objQ(string str)
{
if (str.ToUpper() == "A")
{
clsA objA = new clsA();
return objA;
}
else if (str.ToUpper() == "B")
{
clsB objB = new clsB();
return objB;
}
else
return "";
}
}
Following is clsA:
public class clsA
{
public string strMessage { get; private set; }
public static string staticField;
public bool cantAccessThisFn(string str)
{...}
}
Both of the above classes are in same project which is a class library. I've created another console application wherein I've included the above project's dll. Now, I'm doing:
QMain obj=new QMain();
object A=obj.objQ("A");
I can get strMessage, staticField but not cantAccessThisFn. If I directly make an object of clsA, I'm able to get cantAccessThisFn. Is there any way to get access to this function from obj (object of class QMain)?
I get the following error:
'object' does not contain a definition for 'cantAccessThisFn' and no extension method 'cantAccessThisFn' accepting a first argument of
type 'object' could be found (are you missing a using directive or an
assembly reference?)
The problem is your objQ method returns an object. You haven't defined any (extension) methods on object, so cantAccessThisFn definitely can't be accessed.
What you should do is this: create an interface with all methods you want to share between the two classes, and don't return object, but return IYourInterfaceName. Then you can access those methods and properties defined on the interface.
Something like this:
public class clsA : IYourInterface
{
...
}
public interface IYourInterface
{
string strMessage { get; }
bool cantAccessThisFn(string str);
}
Then your method should look like:
public IYourInterface objQ(string str)
{ ... }
And your assignment like this:
IYourInterface a = obj.objQ("A");
Now it is valid to call:
a.cantAccessThisFn("z");
This is to help you understand! and not the recommended solution.
Marked Patricks answer up, as that is the more correct way...
but to achieve what you had you could do something like.
Also I applied the standard naming camel cases for the Classes, Properties and local variables.
This also allows for ClsA and ClsB to have completely different Method/Property names. Again I am not suggesting this as the way to do it but to rather help understand what its happening.
public class Program
{
static void Main()
{
QMain obj = new QMain();
object a = obj.objQ("A");
//FYI the below commended out is not possible...
//ClsA.staticField is but that is not the instance you created.
//------------
//a.staticField //<--- not possible
//------------
var someA = a as ClsA; //<--- attempts to cast it as ClsA
var someB = a as ClsB; //<--- attempts to cast it as ClsB
if (someA != null) //check if the cast was successful
{
var var1 = someA.StrMessage;
}
else if (someB != null)
{
//...
}
}
}
public class QMain
{
public object objQ(string str)
{
if (str.ToUpper() == "A")
{
ClsA objA = new ClsA();
return objA;
}
else if (str.ToUpper() == "B")
{
ClsB objB = new ClsB();
return objB;
}
else
return "";
}
}
public class ClsA
{
public string StrMessage { get; private set; }
public static string StaticField;
public bool CantAccessThisFn(string str)
{
return true;
}
}
public class ClsB
{
public string StrMessageMyC { get; private set; }
public static string StaticFieldMyC;
public bool CantAccessThisFnMyC(string str)
{
return true;
}
}
I don't get something, and if somebody can clarify:
I need to access this function / helper from here and there:
namespace Laf.Helpers
{
public class Common
{
public string TimeSpanToString(TimeSpan val)
{
return val.ToString(#"hh\:mm");
}
}
}
And in my controller I access it by:
var tmp = new Common();
string str = tmp.TimeSpanToString(tp.DepartureTime);
transferPoint.Add(
new ListTransferPointVM { PortName = tp.PortName, DepartureTime = str }
str);
And the question is how can I achieve and not have duplicate in every controller:
DepartureTime = TimeSpanToString(tp.DepartureTime)
Possible Answer
I just found a way that compiler is not frowning on:
public class TransferController : Controller
{
private Common common = new Common();
public ActionResult Index ()
{
...
and later, when I need it:
string time = common.TimeSpanToString((TimeSpan)variable);
You could make your method string TimeSpanToString(TimeSpan) a static method. This way you can access it without having to make a Common object. Your code will look as follows:
namespace Laf.Helpers
{
public class Common
{
public static string TimeSpanToString(TimeSpan val)
{
return val.ToString(#"hh\:mm");
}
}
}
And your Controller:
transferPoint.Add(
new ListTransferPointVM {
PortName = tp.PortName,
DepartureTime = Common.TimeSpanToString(tp.DepartureTime) }
Common.TimeSpanToString(tp.DepartureTime));
EDIT: As suggested by Michael Petrotta an extension method would be better. An implementation could be:
namespace LaF.ExtensionMethods
{
public static class MyExtensions
{
public static string TimeSpanToString(this TimeSpan ts)
{
return ts.ToString(#"hh\:mm");
}
}
}
You can now call the method like:
tp.DepartureTime.TimeSpanToString();
More on Extension Methods in C#