How to access a string from another method - string

How would I access the string filename from a different method?
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
filename = Server.MapPath("images/") + e.FileName.ToString();
AjaxFileUpload1.SaveAs(filename);
}
I have tried declaring filename in the scope of the class like this:
private string filename = String.Empty;
But when trying to access from another method like this:
public void GetFilename()
{
lblResults.Text = filename;
}
The string is empty. What am I missing?

It depends from the order you call your methods, if your call GetFilename() before AjaxFileUpload1_UploadComplete(...) has been called at least once. Your filename member will be empty, because you initialise it empty.
As you are dealing with asynchronous, you should make sure to wait for filename to be set by your function.

Related

Calling delegate from (get, set )Properties c#

I need help to use the below piece of code to call Method1. There are no compilation issues but while running the code Method1 is not invoked. I searched the net a lot but didn't find a solution.
public static class Test12
{
public static Test12.ByteDelegate PropertyValue { get; set; }
public delegate byte[] ByteDelegate(byte p1, byte[] p2);
}
The above class has to be used like this:
class Abc
{
internal void Stat()
{
Test12.Propertyvalue = Method1;
}
private byte[] Method1(byte p1, byte[] p2)
{
byte[] abc = ...;
return abc;
}
}
If I am creating an instance of the delegate in stat method and using it like:
Method1(param1,param2);
Then the Method1 in invoked, but if I use it like this:
Test12.PropertyValue = Method1(param1,param2);
compiler is throwing an error saying missing typecast. Can anybody please tell me how to invoke Method1 using Test12.PropertyValue = Method1;?
You receive an error message because when you try to assign the method to the delegate you are using the following line of code:
test12.propertyvalue = method1(param1, param2);
Which firstly calls the method1 and then what it returns it's trying to assign to the delegate, and the error message occurs saying that you can't assign a byte array to a delegate, as #Jon said in the comment. They are different types so you can't assign one to another, at least not without a cast or a conversion method.
In order to invoke the method1 from the delegate, after you do the assignation like this:
test12.propertyvalue = method1;
you can simply call the delegate, as it would be your method:
test12.propertyvalue(param1 , param2);

How can I set global field in method

I have some problem, so I have a few global fields in class, for each I want to do the same code but I don't want to repeat code - just use one method for that. And there I want to send these global fields in argument of this method and as second argument I want to send value for this field.
I tried with object, generic type but I don't know how to do that. Here is example:
private void setName(String _name) {
if(isNull(_name)) {
this.name = "";
} else {
this.name = _name.toString();
}
}
And a few other methods use the same code but with other fields and argument and I want to do something like that:
private void setField(some_field, _value) {
if(isNull(_value)) {
this.some_field = "";
} else {
this.some_field = _value;
}
}
Could someone help?
For example I have 2 global fields:
String name, int age.
For them I need to use the same code (if) and I want do it in one method. In this case I have to use global field as argument and as second argument use correct value for this field so instead:
this.name = argument;
this.age=argument;
use: globa_field_argument = argument;
Example:
setField( this.name, "Test" );
setField( this.age, 5 );
First off I would probably declare your global fields as 'public static'.
for example:
public static int myNumber = 10;
public static String myString = "foo";
Secondly you should have to pass your fields as an argument since you can access them inside the method itself.
When you redefine the fields anywhere in your code you will do this:
this.myNumber = newNumber;
this.myString = newString;

How to get a string representation of a property name of a Model in MVC3?

I have the following model:
Public Class MyModel
Public Property MyModelId As Integer
Public Property Description As String
Public Property AnotherProperty As String
End Class
Is there a method to get a property name of the Model as a string representation like the following code?
Dim propertyName as String = GetPropertyNameAsStringMethod(MyModel.Description)
So the propertyName variable has "Description" as value.
Check the Darin Dimitrov' answer on this SO thread - Reflection - get property name.
class Foo
{
public string Bar { get; set; }
}
class Program
{
static void Main()
{
var result = Get<Foo, string>(x => x.Bar);
Console.WriteLine(result);
}
static string Get<T, TResult>(Expression<Func<T, TResult>> expression)
{
var me = expression.Body as MemberExpression;
if (me != null)
{
return me.Member.Name;
}
return null;
}
}
Hope this help..
Here is a helper extension method you can use for any property:
public static class ReflectionExtensions
{
public static string PropertyName<T>(this T owner,
Expression<Func<T, object>> expression) where T : class
{
if (owner == null) throw new ArgumentNullException("owner");
var memberExpression = (MemberExpression)expression.Body;
return memberExpression.Member.Name;
}
}
However, this will only work on instances of a class. You can write a similar extension method that will operate directly on the type instead.
You need to do it using reflection.
There are already loads of posts on stack overflow like this:
How to get current property name via reflection?
Reflection - get property name
Get string name of property using reflection
Reflection - get property name
I believe that the answer will be along the lines of:
string prop = "name";
PropertyInfo pi = myObject.GetType().GetProperty(prop);
Create an extension method and then use it where needed.
Private Shared Function GetPropertyName(Of T)(exp As Expression(Of Func(Of T))) As String
Return (DirectCast(exp.Body, MemberExpression).Member).Name
End Function
have a look at this post as well.
I have solved this issue editing a bit #NiranjanKala's source example,
converting the code in vb.Net like this
<System.Runtime.CompilerServices.Extension()> _
Public Function GetPropertyName(Of T, TResult)(expression As Expression(Of Func(Of T, TResult))) As String
Dim [me] = TryCast(expression.Body, MemberExpression)
If [me] IsNot Nothing Then
Return [me].Member.Name
End If
Return Nothing
End Function
Then I am able to call the extension like this
Dim propertyName as String = GetPropertyName(Of MyModel, String)(Function(x) x.Description)
Then propertyName variable has "Description" as string value.

Overloading a method which accepts `object` as default parameter type

I need to be able to call a method and pass in an object of an unknown type
but then have the correct overload called. I also need a default implementation that accepts
object as its parameter type. What I'm seeing is that the default overload is the only one that ever gets used.
Here's the gist of what I'm trying to do:
class Formatter
{
private object Value;
public Formatter(object val){
Value = val;
}
public override string ToString()
{
return Format(Value);
}
private string Format(object value)
{
return value.ToString();
}
private string Format(DateTime value)
{
return value.ToString("yyyyMMdd");
}
}
Ok, so far so good. Now I want to be able to do this:
public static class FancyStringBuilder()
{
public static string BuildTheString()
{
var stringFormatter = new Formatter("hello world");
var dateFormatter = new Formatter(DateTime.Now);
return String.Format("{0} {1}", stringFormatter, dateFormatter);
}
}
The result of FancyStringBuilder.BuildTheString() is "hello world 2012-12-21 00:00:00.000", when I expected "hello world 20121221"
The problem is that the overload that accepts a DateTime is not being called, instead defaulting to the overload which accepts an object. How can I call the proper method without resorting to a messy switch statement?
In Formatter.ToString(), the override Formatter.Format(object) is always called. This is because the overload resolution happens at compile-time, not run-time. At compile-time, the only thing known about Value is that it's an object.
If you really want to distinguish incoming types, you'll need to do so in Formatter's constructor. In this case, rather than hanging on to the object, you could just call ToString() immediately and only store the formatted result:
class Formatter
{
string formattedValue;
public Formatter(object value)
{
formattedValue = value.ToString();
}
public Formatter(DateTime value)
{
formattedValue = value.ToString("yyyyMMdd");
}
public string ToString()
{
return formattedValue;
}
}
Note that this does assume that your object isn't changing between the time you create the Formatter object and the time Formatter.ToString() is called, or at the very least that it's okay to take a snapshot of the string representation at the time the Formatter is created.
This also assumes that you know the incoming types at compile-time. If you want a truly run-time-only solution, you'll have to use the "is" operator or a typeof() comparison.
If your goal is just to provide custom ToString() formatting based on the incoming type, I'd probably do it using a list that maps from types to format strings:
static class Formatter
{
private static List<Tuple<Type, string>> Formats;
static Formatter()
{
Formats = new List<Tuple<Type, string>>();
// Add formats from most-specific to least-specific type.
// The format string from the first type found that matches
// the incoming object (see Format()) will be used.
AddMapping(typeof(DateTime), "yyyyMMdd");
// AddMapping(typeof(...), "...");
}
private static void AddMapping(Type type, string format)
{
Formats.Add(new Tuple<Type, string>(type, format));
}
public static string Format(object value)
{
foreach (var t in Formats)
{
// If we find a type that 'value' can be assigned to
// (either the same type, a base type, or an interface),
// consider it a match, and use the format string.
if (t.Item1.IsAssignableFrom(value.GetType()))
{
return string.Format(t.Item2, value);
}
}
// If we didn't find anything, use the default ToString()...
return value.ToString();
}
}
With that, calling code then looks like:
Console.WriteLine(
"{0} {1}",
Formatter.Format(DateTime.Now),
Formatter.Format("banana"));
I think this is because the class constructor takes an object as parameter, and then assign that object to variable Value which is also an object. There for calling Format(object) since Value is of type object
Try this
public override string ToString()
{
if(Value is DateTime)
return Format(Convert.ToDateTime(Value)); //this should call the right method
return Format(Value); //works for other non-custom-format types e.g. String
}

Using FieldInfo.SetValue with a DynamicObject as argument 2

I ran into a problem today when trying to set a field using FieldInfo.SetValue() passing a DynamicObject as the second argument. In my case, the field is a Guid and the DynamicObject should be able to convert itself to a one (using TryConvert) but it fails with an ArgumentException.
Some code that shows the problem:
// Simple impl of a DynamicObject to prove point
public class MyDynamicObj : DynamicObject
{
public override bool TryConvert(ConvertBinder binder, out object result)
{
result = null;
// Support converting this to a Guid
if (binder.Type == typeof(Guid))
{
result = Guid.NewGuid();
return true;
}
return false;
}
}
public class Test
{
public Guid MyField;
}
class Program
{
static void Main(string[] args)
{
dynamic myObj = new MyDynamicObj();
// This conversion works just fine
Guid guid = myObj;
var test = new Test();
var testField = typeof(Test).GetField("MyField");
// This, however, fails with:
// System.ArgumentException
// Object of type 'ConsoleApplication1.MyDynamicObj' cannot be converted to type 'System.Guid'.
testField.SetValue(test, myObj);
}
}
I'm not very familiar with the whole dynamicness of C# 4, but this felt to me like something that should work.. What am I doing wrong? Is there another way of doing this?
No, this shouldn't work - because the dynamic portion ends where your code ends. The compiler is calling a method with a signature of
void SetValue(Object obj, Object value)
That method call is dynamic, but it's just going to end up passing in a reference to the instance of MyDynamicObj. The call is resolved at execution time, but nothing in SetValue knows anything about the dynamic nature of the object whose reference you're passing in.
Basically you need to perform the dynamic part (the conversion in this case) in your code - the bit that involves the C# 4 compiler doing all its tricks. You've got to perform that conversion, and then you can call SetField.
To put it another way - it's a bit like calling SetField with a field of type XName, but passing in a string. Yes, there's a conversion from string to XName, but it's not SetField's job to work that out. That's the compiler's job.
Now, you can get this to work by making the compiler do some of the work, but you still need to do some with reflection:
static void Main(string[] args)
{
dynamic myObj = new MyDynamicObj();
var test = new Test();
var testField = typeof(Test).GetField("MyField");
var method = typeof(Program)
.GetMethod("Convert", BindingFlags.Static | BindingFlags.NonPublic);
method = method.MakeGenericMethod(testField.FieldType);
object converted = method.Invoke(null, new object[] {myObj});
testField.SetValue(test, converted);
}
static T Convert<T>(dynamic input)
{
return input;
}
You need an explicit cast to invoke the TryConvert:
testField.SetValue(test, (Guid)myObj);
Not sure if this is what you need though. Maybe there's some way to reflectively say ((DynamicObject)myObj).TryConvert(/*reflected destination type here*/, result)
Other attempts that failed, some of them require things like a certain interface be implemented, so they basically don't make use of TryConvert but maybe an alternative way to accomplish what you want:
Type secondType = testField.FieldType;
TypeConverter tc = TypeDescriptor.GetConverter(typeof(MyDynamicObj));
object secondObject = tc.ConvertTo(myObj,typeof( Guid));
//var secondObject = Convert.ChangeType(myObj, secondType);//Activator.CreateInstance(secondType);
//secondObject = myObj;
testField.SetValue(test, secondObject);

Resources