Im completely stumped on where to go from here.
heres my line of code that i cant get past.
if (error.GetReaction(ErrorReaction.InformUser) == null)
{
error.SetReaction(new ErrorReactionClass(ErrorReaction.InformUser, (CachedAnonymousMethodDelegate1 != null) ? CachedAnonymousMethodDelegate1 : (CachedAnonymousMethodDelegate1 = new Method(ErrorMessageBox.ShowDialog)), "OK", ""));
}
i get the following errors from this
Error 30 'System.Windows.Forms.DialogResult System.Windows.Forms.Form.ShowDialog()' has the wrong return type
Error 31 An object reference is required for the non-static field, method, or property 'System.Windows.Forms.Form.ShowDialog()'
There are two errors here.
The call to ShowDialog doesn't have the return type your delegate is expecting.
You can't call "ShowDialog" on a type, since it's not a static method. You need to provide an actual instance.
I suspect that this may do what you need:
// Not sure how many arguments your "Method" delegate gets
Method showDialog = (arg1, arg2) =>
{
var form = new ErrorMessageBox();
// Setup form with arg1/arg2/etc
form.ShowDialog();
// return appropriate return type here...
};
error.SetReaction(
new ErrorReactionClass(
ErrorReaction.InformUser,
(CachedAnonymousMethodDelegate1 != null)
? CachedAnonymousMethodDelegate1
: (CachedAnonymousMethodDelegate1 = showDialog)
, "OK", ""));
Related
I'm running into an odd scenario that doesn't happen on my PC, but does for a coworkers.
I have this piece of code:
LoaderHelpers.SetStringValue<blah>(this, "x", $"x response in Header",
() => jsonData.x.response[0].value, false);
The problem is that sometimes, "jsonData.x" is null and, for my coworker a 'cannot bind to null at runtime exception' is thrown, but not for me there isn't. I have code to handle the null scenario, but it's like his code never gets to that point and fails at the call level.
jsonData is of type dynamic.
The method code that handles the null scenario:
public static void SetStringValue<T>(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if (data.GetType().GetProperty(propertyName) != null)
{
try
{
if (string.IsNullOrEmpty(value()))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
else
{
data.GetType().GetProperty(propertyName).SetValue(data, value());
}
}
catch
{
//property doesn't exist
if (required)
data.DataValidationErrors.Add($"{valuePath} doesn't exist");
data.GetType().GetProperty(propertyName).SetValue(data, null);
}
}
else
{
throw new NullReferenceException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
}
}
Again. Works perfect for me, but not for him. I'm completely lost. Maybe I don't understand how the lamba/function parameters work 100%, but I thought it only got evaluated when value() is invoked.
I should also mention that when I debug this code, I can step into the Nuget package and when he hits the same line, he can't. This maybe a useful hint.
If jsonData (or jsonData.x) is null (as it seems to be at this point) it will crash and give you that error every time you call the method value().
You need to check why jsonData.x is null. Maybe it´s a race condition caused by another thread setting this value to null, maybe it´s because a bad jsonData initialization... Can´t say since that code is not here.
There are so many things wrong with your code, i can't resist.
First of all, instead of copy/pasting the same stuff over and over, you might want to use a variable:
var property = data.GetType().GetProperty(propertyName);
Second, you pass a Func<string> and execute it multiple times, why is it even a function then? Yet again, better only evaluate it once and use a variable...
var unwrapped = value();
That would solve the issue, that Roberto Vázquez' answer adresses.
Then you are misusing NullReferenceException, instead rather use a ArgumentException
Next issue, that valuePath is only used in the exception message, that is a poor design to my beliefs.
The generic T parameter isnt even used, so get rid of it.
Last but not least, that catch-block doing the exact thing that could possibily throw the exception again, i cant see any reason why you would do this.
Finnaly this whole thing becomes a little more clear but its still a mess.
public static void SetStringValue(IValidate data, string propertyName,
string valuePath, Func<string> value, bool required)
{
if(data == null)
throw new ArgumentNullException(nameof(data));
var property = data.GetType().GetProperty(propertyName);
if(property == null)
throw new ArgumentException($"In {data.GetType()} => SetStringValue. " +
$"Passed property {propertyName}, but property doesn't exist.");
var unwrapped = value();
try
{
if (string.IsNullOrEmpty(unwrapped))
{
if (required)
data.DataValidationErrors.Add($"{valuePath} can't be empty");
unwrapped = null; // this might be unecessary.
}
property.SetValue(data, unwrapped);
}
catch(Exception e)
{
// This is probably a bad idea.
property.SetValue(data, null);
if (required)
data.DataValidationErrors.Add(Atleast put a better message here. e.Message ...);
}
}
I'm making a managed .NET debugger using MDBG sample.
MDBG has no support for property getters evaluation, which I'm trying to add. Please, consider following class structure:
public abstract class Base<T>{
public string SomeProp {get;set;}
}
public class A : Base<int>{
}
At some point of time I'm creating an instance of A and stopping at a breakpoint to evaluate it's state.
In my debugger's watch window I introduce "this.SomeProp", that should perform a func-eval of get_SomeProp method on this object and return a null value for given case.
The first issue I've encountered was the fact, that get_SomeProp was defined on the base class, so I had to run through all TypeDefs/TypeRefs/TypeSpecs in the class hierarchy to find the function.
But after it was found, calling
ICorDebugEval.CallFunction(function.CorFunction, new[] {#object.CorValue});
resulted in: TypeLoadException: The generic type was used with the wrong number of generic arguments in assembly.
As I've realized it happens because non-generic function is defined in a generic class (Base), so when I'm evaluating it I should also indicate class's generic params.
This could be done using
ICorDebugEval2.CallParameterizedFunction(function.CorFunction,
genericArguments,
functionArguments);
The problem is that I have no idea how to extract types of class generic parameters, having only function that I want to evaluate and instance on which I want to evaluate it.
Here is some code I'm currently using:
private MDbgValue EvaluatePropertyGetter(MDbgFrame scope, MDbgValue #object, string propertyName) {
var propertyGetter = $"get_{propertyName}";
var function = ResolveFunctionName(
scope.Function.Module.CorModule.Name,
#object.TypeName,
propertyGetter,
scope.Thread.CorThread.AppDomain);
if (function == null) {
throw new MDbgValueException("Function '" + propertyGetter + "' not found.");
}
var eval = Threads.Active.CorThread.CreateEval();
var typeToken = function.CorFunction.Class.Token;
var type = function.Module.Importer.GetType(typeToken); //checked that type containing function is generic
if (type.IsGenericType) {
//------------->need to get class'es generic param types<------------
var genericType1 = this.ResolveType("System.Object"); // just a stub
eval.CallParameterizedFunction(function.CorFunction, new CorType[] {genericType1}, new[] {#object.CorValue});
}
else {
eval.CallFunction(function.CorFunction, new[] {#object.CorValue});
}
Go().WaitOne();
if (!(StopReason is EvalCompleteStopReason)) {
// we could have received also EvalExceptionStopReason but it's derived from EvalCompleteStopReason
Console.WriteLine("Func-eval not fully completed and debuggee has stopped");
Console.WriteLine("Result of funceval won't be printed when finished.");
}
else {
eval = (StopReason as EvalCompleteStopReason).Eval;
Debug.Assert(eval != null);
var cv = eval.Result;
if (cv != null) {
var mv = new MDbgValue(this, cv);
return mv;
}
}
return null;
}
Any suggestion/advice is greatly appreciated!
Regards,
Solution
Thanks to #Brian Reichle outstanding answer I came up with this solution:
if (type.IsGenericType) {
//getting Type's Generic parameters
var typeParams = GetGenericArgs(#object.CorValue.ExactType, function.CorFunction.Class.Token);
eval.CallParameterizedFunction(function.CorFunction, typeParams.ToArray(), new[] {#object.CorValue});
}
And the function itself:
private List<CorType> GetGenericArgs(CorType corType, int classTk) {
if (corType == null)
return null;
List<CorType> list = new List<CorType>();
var param =corType.TypeParameters;
var args = GetGenericArgs(corType.Base, classTk);
if (classTk == corType.Class.Token) {
list.AddRange(param.Cast<CorType>());
}
if (args != null) {
list.AddRange(args);}
return list;
}
You can use ICorDebugValue2::GetExactType on the value object representing an instance of A to get the ICorDebugType for type A, ICorDebugType::GetBase() to get its base class (Base<int>) and ICorDebugType::EnumerateTypeParameters on the base type to get it's type arguments.
I know this question has been asked before. I have the code to do this but i am getting an error and I think I know why but I am just really getting into .Net Reflection so I wish to get confirmation on whether I am correct or not.
Here is the code. I want to retrieve all the forms from my project that have a basetype of "BaseEditForm" and then all of those that end with "EditForm" I want to put in a List to populate a ListBox.
public void LoadAllEditForms()
{
formsList = new List<string>();
try
{
Assembly project = Assembly.Load("UnionAdministrator");
foreach (Type t in project.GetTypes())
{
if (t.BaseType == typeof (BaseEditForm))
{
var emptyCtor = t.GetConstructor(Type.EmptyTypes);
if (emptyCtor != null)
{
var f = (Form) emptyCtor.Invoke(new object[] {});
if (f.Name.EndsWith("EditForm"))
formsList.Add(f.Name);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am getting the error message "Object reference not set to an instance of an object." on the line
var f = (Form) emptyCtor.Invoke(new object[] {});
emptyCtor is not null and besides there is no way for emptyCtor to get to this point if it is null. So I am confused about the error message. So here is my question. For this to work properly do all my forms have to have a default constructor? Almost all my forms have a constructor that takes one or more parameters. Is that my problem?
Your code works fine.
It must be one of your constructors that throw the exception.
Check all of your derived Forms to see if any of them (those that does not take any ctor parameters) could throw a NullReferenceException if invoked.
I'm not sure why you're going through the trouble of trying to execute the constructor of every form. You could simplify your code (and avoid the whole issue) by just looking at the type names.
public void LoadAllEditForms()
{
Assembly project = Assembly.Load("UnionAdministrator");
var formsList = project.GetTypes()
.Where (t => t.BaseType == typeof(BaseEditForm) && t.Name.EndsWith("EditForm"))
.ToList();
}
I am making a save option in my program that saves the changes to a file. I am using this code to save and get a MessageBox to show the result of the process I am getting an error on this line "Object reference not set to an instance of an object."
SaveFileCheck = StockHandler.SaveChangesToFile();
this is my code
private void Save_Click(object sender, EventArgs e)
{
bool SaveFileCheck = false;
var result = MessageBox.Show("Are you sure you want to Save the changes ?", "My Application",
MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);
if (result == DialogResult.Yes)
{
SaveFileCheck = StockHandler.SaveChangesToFile();
if (SaveFileCheck)
{
MessageBox.Show("The process was a success");
}
else
{
MessageBox.Show("The process failed please make sure that the file is not been used and try again");
}
//Save the file back
}
}
}
}
public bool SaveChangesToFile()
{
try
{
if (FileName != null)
{
using (StreamWriter Write = new StreamWriter(FileName, false))
{
foreach (Stock s in FileStockList)
{
Write.Write(s.ToString() + "\r\n");
}
}
}
else {
return false;
}
}
catch(IOException ex)
{
return false;
throw new ArgumentException("something went wrong an error" + ex + "is been cought");
}
return true;
}
StockHandler is null.
If StockHandler is not a static class, you need to create an instance of it before you can call methods on it:
var handler = new StockHandler();
SaveFileCheck = handler.SaveChangesToFile();
Or, if StockHandler is a member variable:
StockHandler = new // something
You haven't shown what StockHandler is, or where you're getting it from - but it looks like it's null. You'll need it to be a reference to a valid object. There's not a lot more we can say just from the code you've given.
Note that this has nothing to do with a method returning a bool.
It could be that StockHandler is null, or something in the SaveChangesToFile method is null or invalid.
EDIT
See here:
private StockHelper StockHandler;
StockHandler.SaveChangesToFile(); // = bang :(
You need to initialize the StockHelper instance:
private StockHelper StockHandler = new StockHelper();
StockHandler.SaveChangesToFile(); // = okay :)
I'm assuming that this code doesn't compile, which probably means that StockHandler is null. Otherwise, the error would likely be pointing to the SaveChangesToFile method.
Secondly, you either need to swallow exceptions in the SaveChangesToFile() method (not advisable), or you need to remove the return statement and throw the exception. If you do decide to throw an exception, it should definitely not be an ArgumentException, as it has nothing to do with arguments supplied to the method (or lack thereof).
What is stockhandler -- your SaveChangesToFile method is an instance method -- so have you instantiated a variable 'StockHandler' to an instance of whatever class contains the method SaveChangesToFile();
I get a null exception if I try to pass a null parameter to a delegate during an invoke. Here's what the code looks like:
public void RequestPhoto()
{
WCF.Service.BeginGetUserPhoto(Contact.UserID,
new AsyncCallback(RequestPhotoCB), null);
}
public void RequestPhotoCB(IAsyncResult result)
{
var photo = WCF.Service.EndGetUserPhoto(result);
UpdatePhoto(photo);
}
public delegate void UpdatePhotoDelegate(Binary photo);
public void UpdatePhoto(Binary photo)
{
if (InvokeRequired)
{
var d = new UpdatePhotoDelegate(UpdatePhoto);
Invoke(d, new object[] { photo });
}
else
{
var ms = new MemoryStream(photo.ToArray());
var bmp = new Bitmap(ms);
pbPhoto.BackgroundImage = bmp;
}
}
The problem is with the line:
Invoke(d, new object[] { photo });
If the variable "photo" is null. What is the correct way to pass a null parameter during an invoke?
Thanks!
Just for the benefit of others, you can pass null arguments to delegates (if the type allows it? Clarification needed here). In your case, IAsyncResult will allow it.
As for the debugging, the exception occurs on Invoke because you are debugging on a given Thread A, the exception occurs on Thread B. You can breakpoint multiple threads. Breakpoint the Thread B code and you will see the exception closer to or on the source.
Notice though that your debugger will jump around if multiple threads are running code at the same time. Debugging in multiple threads is always at least a little tricky, but satisfying when you solve the problems.
You could also further improve your answer code to check the null before it checks the InvokeRequired, as this is thread-independent to your logic (your code checks it just prior to use, after Invoking). This will save pushing the Invoke onto the message pump (assuming WinForms).
OK I figured it out. The problem was NOT with passing the null parameter to the delegate like I thought. The problem was with the delegate executing it was causing a null exception on the line:
var ms = new MemoryStream(photo.ToArray());
I didn't realize the problem was there because it was crashing on the Invoke line.
So I changed the UpdatePhoto method as follows:
public void UpdatePhoto(Binary photo)
{
if (InvokeRequired)
{
var d = new UpdatePhotoDelegate(UpdatePhoto);
Invoke(d, new object[] { photo});
}
else
{
if (photo != null)
{
var ms = new MemoryStream(photo.ToArray());
var bmp = new Bitmap(ms);
pbPhoto.BackgroundImage = bmp;
}
}
}
And all is well!