I simply want to see if a string can be converted to any valid type using: System.ComponentModel.TypeDescriptor.GetConverter(type).IsValid(value)) type is System.Type and value is System.String.
I get the following message at Runtime on the line that I call the aforementioned method: System.IO.FileNotFoundException: 'Could not load file or assembly 'Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. The system cannot find the file specified.'
Visual Studio also gives me the call stack and the first entry is, External Code.
This exception was originally thrown at this call stack:
[External Code]
MyProgram.Core.Extensions.CanCovertToValue(string) in Extensions.cs
MyProgram.Core.Parser.IdentifyTokens(string[]) in Parser.cs
Program.Main(string[]) in Program.cs
Here's the method it's used in:
public static bool CanCovertToValue(this string value)
{
foreach (Type type in Types)
{
if (System.ComponentModel.TypeDescriptor.GetConverter(type).IsValid(value))
{
if (type == typeof(string))
{
if (value.StartsWith("\"") && value.EndsWith("\""))
{
return true;
}
else
{
continue;
}
}
else if (type == typeof(Uri))
{
if (value.StartsWith("\"") && value.EndsWith("\""))
{
return true;
}
else
{
continue;
}
}
if (type == typeof(char))
{
if (value.StartsWith("'") && value.EndsWith("'"))
{
return true;
}
else
{
continue;
}
}
else
{
return true;
}
}
}
return false;
}
The problem turned out to be that I was trying to iterate through custom structs of a referenced library that references a different version of Newtonsoft.Json. It works perfectly fine with built in C# types.
Related
I have some assemblies (DLLs) embedded as a resource (in resource designer).
At runtime I am trying to load them. To do so I have subscribed to an event like below:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
and then the method is the following:
public System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
try
{
Assembly a2 = Assembly.Load(Properties.Resources.OneDLL);
return a2;
}
catch (Exception ex)
{
// do something
}
return null;
}
Above code works well when I only have a DLL embedded as a resource in my app because I know which one to load through Properties.Resources.OneDLL as in the example above.
The problem is when I have some DLLs embedded as a resource, I mean, in the method above, once event is raised, I do not know what DLL is in order to load it.
Within this method how can I know which DLL is and load it accordingly?
In the method above I know args.Name contains the name of the DLL to load but is a string followed by other information like version, culture, etc... :
"mynamespace.OneDLL, Version=2.3.0.0, Culture=neutral, PublicKeyToken=null"
Method would be something like this:
public System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
try
{
Assembly a2;
if (args.Name == 'OneDLL')
{
a2 = Assembly.Load(Properties.Resources.OneDLL);
}
else if (args.Name == 'AnotherDLL')
{
a2 = Assembly.Load(Properties.Resources.AnotherDLL);
}
else if (args.Name == 'AnotherAnotherDLL')
{
a2 = Assembly.Load(Properties.Resources.AnotherAnotherDLL);
}
else
{
return null;
}
return a2;
}
catch (Exception ex)
{
// do something
}
return null;
}
Finally I have done below and it is working:
public System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
Assembly assembly;
string strAssembly;
strAssembly = args.Name.Split(',')[0].ToString();
assembly = null;
try
{
Assembly assembly ;
if (strAssembly == 'OneDLL')
{
assembly = Assembly.Load(Properties.Resources.OneDLL);
}
else if (strAssembly == 'AnotherDLL')
{
assembly = Assembly.Load(Properties.Resources.AnotherDLL);
}
else if (strAssembly == 'AnotherAnotherDLL')
{
assembly = Assembly.Load(Properties.Resources.AnotherAnotherDLL);
}
else
{
// do something
return assembly;
}
return assembly;
}
catch (Exception ex)
{
// do something
}
return assembly;
}
Please, If someone has a better idea to do it, please share.
I am using the MVVM Light library. From this library I use RelayCommand<T> to define commands with an argument of type T.
Now I have defined a RelayCommand that requires an argument of type Nullable<bool>:
private RelayCommand<bool?> _cmdSomeCommand;
public RelayCommand<bool?> CmdSomeCommand
{
get
{
if (_cmdSomeCommand == null)
{ _cmdSomeCommand = new RelayCommand<bool?>(new Action<bool?>((val) => { /* do work */ })); }
return _cmdSomeCommand;
}
}
How can I assign the CommandParameter from my XAML code?
I've tried to pass a boolean value, but that causes the following exception:
System.InvalidCastException: Invalid cast from 'System.Boolean' to 'System.Nullable`1[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
I've also tried to define static properties containing the bool? values and reference them from XAML:
public static class BooleanHelper
{
public static bool True { get { return true; } }
public static bool False { get { return false; } }
public static bool? NullableTrue { get { return true; } }
public static bool? NullableFalse { get { return false; } }
}
XAML:
<Button Command="{Binding CmdSomeCommand}" CommandParameter="{x:Static my:BooleanHelper.NullableTrue}" />
But this causes the same exception to be thrown. I've also tried to return new Nullable<bool>(true), but as expected, this has the same result.
Looks like MVVM Light is at fault for handling the parameter differently between Execute and CanExecute and not handling nullable in a proper way.
See the code at https://github.com/paulcbetts/mvvmlight/blob/master/GalaSoft.MvvmLight/GalaSoft.MvvmLight%20(NET35)/Command/RelayCommandGeneric.cs#L198 Lines 198-205
What happens there leads to your exception and can be easily reproduced with the following code:
object t1 = (bool?)true;
// issue: for Nullable<T>, GetType will return T
if (t1.GetType() != typeof(bool?))
{
if (t1 is IConvertible)
{
var val = Convert.ChangeType(t1, typeof(bool?), null);
}
}
I suspect you can only file a bug report, because you can perfectly pass the nullable as parameter, it is handled with errors.
I have a project (class library project) with target version .NET Framework 3.5.
I am accessing a string (SplittedPermanentAddressAsString) using get method
if (!Util.isEmpty(cardDetails.SplittedPermanentAddressAsString))
{
permanentAddressStr += cardDetails.SplittedPermanentAddressAsString;
}
and here is the Property
public string SplittedPermanentAddressAsString
{
get
{
if (PermanentAddress != null)
{
return PermanentAddress.SplittedFullAdrsEn;
}
else
{
return "";
}
}
}
When i run the application, i find following error
"Method not found: 'System.String HSDLServerAdminLib.Entity.Card.CardDetails.get_SplittedPermanentAddressAsString()'.
Stack Trace: at HSDLAdminPortal.ServiceImpl.Card.CardViewDetailImpl.viewDetailInfo(Object view, Object res)
at HSDLAdminPortal.Controller.Card.CardDetailsController.worker_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
I want to decompile a method in my assembly, which references e.g. 'Microsoft.SharePoint.dll', but I have no SharePoint installed on the machine.
If I use the following code I get an Mono.Cecil.AssemblyResolutionException 'failed to resolve assembly Microsoft.SharePoint...'.
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly("PathToMyAssembly");
ICSharpCode.Decompiler.DecompilerContext context = new ICSharpCode.Decompiler.DecompilerContext(assembly.MainModule);
AstBuilder decompiler = new AstBuilder(context);
decompiler.AddMethod(method); <!-- here it crashes -->
With the ILSpy GUI I can load my assembly without errors (on the same machine without SharePoint).
What do I need to change in my code?
I found the solution myself. I created my own AssemblyResolver which catches the AssemblyResolutionException and returns null for missing referenced assemblies.
public class MyDefaultAssemblyResolver : DefaultAssemblyResolver
{
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
try
{
return base.Resolve(name);
}
catch { }
return null;
}
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
try
{
return base.Resolve(name, parameters);
}
catch { }
return null;
}
public override AssemblyDefinition Resolve(string fullName)
{
try
{
return base.Resolve(fullName);
}
catch { }
return null;
}
public override AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
{
try
{
return base.Resolve(fullName, parameters);
}
catch { }
return null;
}
}
Then I use it
var resolver = new MyDefaultAssemblyResolver();
resolver.AddSearchDirectory("FolderOfMyAssembly");
var parameters = new ReaderParameters
{
AssemblyResolver = resolver,
};
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly("PathToMyAssembly", parameters);
I found the solution by debugging the ILSpy GUI (source code is fortunately available).
I'd like to instantiate a class by name (a string) without specifying a namespace or assembly. Like this (Unity syntax):
var processor = container.Resolve<IProcessor>("SpecialProcessor");
would instantiate the first IProcessor it finds called SpecialProcessor. Maybe
MyNamespace.SpecialProcessor
I'd like to avoid having to create an entry in a config every time somebody adds a new processor. I'm fine with having an entry for all candidate assemblies though.
Can I use an IoC container for something like this or should I roll my own?
Here's a function that does something very similar to what you want. You can modify it to filter based on a specific class name pretty easily.
These functions have references to a few utilities we use for logging and exception handling. You'll need to replace them with whatever you normally do in these situations.
public static T FindAndCreate<T>(bool localOnly, bool exportedOnly)
{
Type[] types = FindAssignableClasses(typeof(T), localOnly, exportedOnly, false);
if (types.Length == 0)
{
return default(T);
}
if (types.Length != 1)
{
Log.Warn(typeof(ReflectionUtil),
"FindAndCreate found {0} instances of {1} whereas only 1 was expected. Using {2}. {3}",
types.Length,
typeof(T).FullName,
types[0].FullName,
String.Join("\r\n ", Array.ConvertAll<Type, String>(types, GetFullName)));
}
try
{
return (T)Activator.CreateInstance(types[0]);
}
catch (Exception ex)
{
throw ExceptionUtil.Rethrow(ex,
"Unable to create instance of {0} found for interface {1}.",
types[0].FullName,
typeof(T).FullName);
}
}
public static Type[] FindAssignableClasses(Type assignable, bool localOnly, bool exportedOnly, bool loadDll)
{
var list = new List<Type>();
string localDirectoryName = Path.GetDirectoryName(typeof(ReflectionUtil).Assembly.CodeBase);
if (loadDll && !_loadedAllDlls)
{
foreach (string dllPath in Directory.GetFiles(localDirectoryName.Substring(6), "*.dll"))
{
try
{
Assembly.LoadFrom(dllPath);
}
catch
{
// ignore
}
}
_loadedAllDlls = true;
}
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
if (localOnly && Path.GetDirectoryName(asm.CodeBase) != localDirectoryName)
{
continue;
}
Type[] typesInAssembly;
try
{
typesInAssembly = exportedOnly ? asm.GetExportedTypes() : asm.GetTypes();
}
catch
{
continue;
}
foreach (Type t in typesInAssembly)
{
try
{
if (assignable.IsAssignableFrom(t) && assignable != t)
{
list.Add(t);
}
}
catch (Exception ex)
{
Log.Debug(
typeof(ReflectionUtil),
String.Format(
"Error searching for types assignable to type {0} searching assembly {1} testing {2}{3}",
assignable.FullName,
asm.FullName,
t.FullName,
FlattenReflectionTypeLoadException(ex)),
ex);
}
}
}
catch (Exception ex)
{
// ignore dynamic module error, no way to check for this condition first
// http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/7b02223aefc6afba/c8f5bd05cc8b24b0
if (!(ex is NotSupportedException && ex.Message.Contains("not supported in a dynamic")))
{
Log.Debug(
typeof(ReflectionUtil),
String.Format(
"Error searching for types assignable to type {0} searching assembly {1} from {2}{3}",
assignable.FullName,
asm.FullName,
asm.CodeBase,
FlattenReflectionTypeLoadException(ex)),
ex);
}
}
}
return list.ToArray();
}
It sounds like you have a plugin architecture and you want to allow other components to provide implementations of IProcessor without having to update some master config file. If that's the case, then I think you are best suited by using MEF (managed extensibility framework) (Website).
This is a framework designed to allow such behavior. Once you establish a catalog of assemblies to load components from, importing the collection of IProcessor instances is as easy as the following
var processors = container.GetExportedValues<IProcessor>();
There are many tutorials online for MEF that should get you started.