So I have the following ViewModel:
using Prism.Commands;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using TrackIt.Model;
using TrackIt.UI.Event;
namespace TrackIt.UI.ViewModel
{
public class NavigationItemViewModel : ViewModelBase
{
private string _displayMember;
private IEventAggregator _eventAggregator;
private string _detailViewModelName;
public NavigationItemViewModel(int id,
IEventAggregator eventAggregator,
string detailViewModelName)
{
Id = id;
_detailViewModelName = detailViewModelName;
OpenDetailViewCommand = new DelegateCommand(OnOpenDetailViewExecute);
_eventAggregator = eventAggregator;
}
public int Id { get; }
public ICommand OpenDetailViewCommand { get; set; }
private void OnOpenDetailViewExecute()
{
_eventAggregator.GetEvent<TestEvent>()
.Publish(Id);
_eventAggregator.GetEvent<OpenDetailViewEvent>()
.Publish(
new OpenDetailViewEventArgs
{
Id = Id,
ViewModelName = _detailViewModelName
}
);
}
}
}
Thus I have an ICommand above, that upon executing, will trigger the TestEvent and OpenDetailViewEvent events, with the TestEvent having an integer argument, and the OpenDetailViewEvent having a custom class argument OpenDetailViewEventArgs class.
I'm testing that upon executing the command, the Publish method of each event is called. I use Moq to mock the GetEvent calls. This is my code:
using Moq;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TrackIt.UI.Event;
using TrackIt.UI.ViewModel;
using Xunit;
namespace TrackIt.UITests.ViewModel
{
public class NavigationItemViewModelTests
{
[Fact]
public void ShouldPublishOpenFriendDetailViewEvent()
{
const string displayMember = "test string";
const int id = 4;
const string detailViewMemberName = nameof(FriendDetailViewModel); // Just take a random detail view
var _mockedOpenDetailViewEvent = new Mock<OpenDetailViewEvent>();
var _mockedTestEvent = new Mock<TestEvent>();
var eventAggregatorMock = new Mock<IEventAggregator>();
eventAggregatorMock
.Setup(dp => dp.GetEvent<OpenDetailViewEvent>())
.Returns(_mockedOpenDetailViewEvent.Object);
eventAggregatorMock
.Setup(dp => dp.GetEvent<TestEvent>())
.Returns(_mockedTestEvent.Object);
var _itemViewModel = new NavigationItemViewModel(id,
displayMember, eventAggregatorMock.Object, detailViewMemberName);
_itemViewModel.OpenDetailViewCommand.Execute(null);
_mockedTestEvent.Verify(e => e.Publish(id),
Times.Once);
_mockedOpenDetailViewEvent.Verify(e => e.Publish(new OpenDetailViewEventArgs { Id = id, ViewModelName = detailViewMemberName }),
Times.Once);
}
}
}
The thing is, the test passes the Verify for TestEvent event, but it fails for OpenDetailViewEvent with error Expected invocation on the mock once, but was 0 times, even though I debugged and saw the event actually published. Maybe it's because I'm supplying a custom class as its argument, while TestEvent uses a native C# class (i.e. int)? How to fix this?
Use an argument matcher instead since the instances can't be the same object reference in this scenario.
// ....
_mockedOpenDetailViewEvent
.Verify(
_ => _.Publish(It.Is<OpenDetailViewEventArgs>(arg => arg.Id == id && arg.ViewModelName == detailViewMemberName)),
Times.Once
);
It.Is above is used to create a predicate to match the argument that was used to invoke the member.
Related
The error I got :
"object" doesn't contain a definition for "test"
I also tried game.test() but I keep getting this error
This solution is divided in two distinct projects :
The first one is a .dll
The second one is a console
the goal is to call the get method from the 'iw4mp' class dynamicaly. So I would be able to call any from the class while it will be loaded.
the COD class should look useless but in the futur it will look if the process is running on the computer but for my test I use a string (but it actually work same way as if it was looking for a process).
Code from the DLL
COD
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CODOffsets.Interface;
using CODOffsets.Offsets;
namespace CODOffsets
{
public class COD
{
static string[] games = { "iw4mp", "iw5mp", "bo1" };
static Type CallofDuty;
public static bool checkGame()
{
foreach (string game in games)
{
if (ProcessHandle(game))
{
CallofDuty = Type.GetType("CODOffsets.Offsets" + "." + game);
return true;
}
}
return false;
}
public static object Game()
{
return Activator.CreateInstance(CallofDuty) as ICODClass;
}
public static bool ProcessHandle(string game)
{
if (game == "iw4mp")
return true;
else
return false;
}
}
}
Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CODOffsets.Interface
{
interface ICODClass
{
string test { get; }
}
}
Offset
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CODOffsets.Interface;
namespace CODOffsets.Offsets
{
class iw4mp : ICODClass
{
public string test { get { return "this is mw2"; } }
}
}
Code from the Console project
Main
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CODOffsets;
namespace TestGenericClass
{
class Program
{
static void Main(string[] args)
{
if (COD.checkGame())
{
dynamic game = COD.Game();
Console.WriteLine(game.test);
Console.ReadKey();
}
}
}
}
It should basically work as the way you did. But, if not so, here are some alternatives.
you can use reflections in c# to get all the properties of the dynamic object.
var nameOfProperty = "test";
var propertyInfo = game.GetType().GetProperty(nameOfProperty);
var value = propertyInfo.GetValue(game, null);
Moreover, you can simply use this way to get the value if you know the property name
string value = game["test"];
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I am using VS'15 on asp.net 4.6.
I am also modeling my application after the N-Tier design found at:
Implementing a generic data access layer using Entity Framework
I am able to return data from a User table, however when using code based on the User code to return data from another table, I get a null return.
My BLL code that works:
using System;
using System.Collections.Generic;
using System.Linq;
using Library.DataAccessLayer;
using Library.Model;
namespace Library.BusinessLogicLayer
{
public interface IBusinessLogicLayer_User
{
IList<UsersModel> GetAllUsers();
UsersModel GetUserByAapNetUserID(string _UserID);
void UpdateUser(params UsersModel[] _UserModel);
}
public class BusinessLogicLayer_User : IBusinessLogicLayer_User
{
private readonly IUsersRepository _UsersRepository;
public BusinessLogicLayer_User()
{
_UsersRepository = new UsersRepository();
}
public BusinessLogicLayer_User(IUsersRepository userRepository)
{
_UsersRepository = userRepository;
}
public IList<UsersModel> GetAllUsers()
{
return _UsersRepository.GetAll();
}
public UsersModel GetUserByAapNetUserID(string _UserID)
{
return _UsersRepository.GetSingle(u => u.AspNetUserID.Equals(_UserID));
}
public void UpdateUser(params UsersModel[] _UsersModel)
{
_UsersRepository.Update(_UsersModel);
}
}
}
My BLL code that does not work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Library.DataAccessLayer;
using Library.Model;
namespace Library.BusinessLogicLayer
{
public interface IBusinessLogicLayer_AreaSecurity
{
AreaSecurityModel GetAreaSecurityByUserID(string _AspNetUserID);
void AddAreaSecurity(params AreaSecurityModel[] _AreaSecurityModel);
void UpdateAreaSecurity(params AreaSecurityModel[] _AreaSecurityModel);
IList<AreaSecurityModel> GetAllAreaSecurity();
}
public class BusinessLogicLayer_AreaSecurity : IBusinessLogicLayer_AreaSecurity
{
private readonly IAreaSecurityRepository _AreaSecurityRepository;
public BusinessLogicLayer_AreaSecurity()
{
_AreaSecurityRepository = new AreaSecurityRepository();
}
public BusinessLogicLayer_AreaSecurity(IAreaSecurityRepository areaSecurityRepository)
{
_AreaSecurityRepository = areaSecurityRepository;
}
public void AddAreaSecurity(params AreaSecurityModel[] _AreaSecurityModel)
{
_AreaSecurityRepository.Add(_AreaSecurityModel);
}
public IList<AreaSecurityModel> GetAllAreaSecurity()
{
return _AreaSecurityRepository.GetAll();
}
public AreaSecurityModel GetAreaSecurityByUserID(string _AspNetUserID)
{
return _AreaSecurityRepository.GetSingle(r => r.AspNetUserID.Equals(_AspNetUserID));
}
public void UpdateAreaSecurity(params AreaSecurityModel[] _AreaSecurityModel)
{
_AreaSecurityRepository.Update(_AreaSecurityModel);
}
}
}
And here is the code that is calling the stuff that works and does not work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Library.BusinessLogicLayer;
using Library.Model;
namespace IdahoFalls9thWardBulletin.Controllers
{
public class ApplicationBaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (User != null)
{
var context = new ApplicationDbContext();
var username = User.Identity.Name;
if (!string.IsNullOrEmpty(username))
{
var user = context.Users.SingleOrDefault(u => u.UserName == username);
BusinessLogicLayer_User _BusinessLogicLayer_User = new BusinessLogicLayer_User();
var UserDetails = _BusinessLogicLayer_User.GetUserByAapNetUserID(user.Id);
ViewData.Add("FirstName", UserDetails.FirstName);
BusinessLogicLayer_AreaSecurity _BusinessLogicLayer_AreaSecurity = new BusinessLogicLayer_AreaSecurity();
AreaSecurityModel _AreaSecurityModel = _BusinessLogicLayer_AreaSecurity
.GetAllAreaSecurity()
.ToList()
.FirstOrDefault();
ViewData.Add("AreaSecurity", _AreaSecurityModel);
}
}
base.OnActionExecuted(filterContext);
}
public ApplicationBaseController()
{
}
}
}
What I do not understand is that when I do _BusinessLogicLayer_AreaSecurity.GetAllAreaSecurity().ToList().FirstOrDefault() It does in fact return the list of all records.
However when I do _BusinessLogicLayer_AreaSecurity.GetAllAreaSecurity().GetAreaSecurityByUserID(user.Id) It returns the null value.
I have no idea what I am missing here. This is basically my first attempt at MVC code first.
I am ashamed to say that the problem is that my database for the security table is set as a Guid not a string.
I am trying to make a (my first MEF) system in which plugins can be recursive, i.e. my main system calls a MEF plugin with a standard interface, which on its own can then call another (or several) plugin(s), and so on.
When testing though, my plugin does not call the underlying plugin, but starts processing itself (creating a loop).
Any idea how I can prevent this?
Interface:
public interface IConnector
{
XDocument Run(object serviceCredentials, object connectorIds, object connectorKeys);
}
My main plugin inherits the interface, and defines the import for the next (The subplugin has the same definition):
[Export(typeof(IConnector))]
public class Connector : IConnector
{
[Import(typeof(IConnector))]
private IConnector connector;
....
The called plugin is initiated (in the Run method of the main plugin):
public XDocument Run(object serviceCredentials, object connectorIds, object connectorKeys)
{
string calledConnector = Path.Combine(AssemblyDirectory, "subplugin.dll");
AssemblyCatalog assembyCatalog = new AssemblyCatalog(Assembly.LoadFrom(calledConnector));
CompositionContainer container = new CompositionContainer(assembyCatalog);
container.ComposeParts(this);
....
The container should now contain just one plugin, the subplugin.dll.
I call the method 'Run' which is in the interface to invoke the subplugin method:
XDocument something = connector.Run(serviceCredentials, connectorids, connectorkeys);
But, instead of running the subplugin code, the 'Run' method in my main plugin activates, which keeps activating itself.
When I remove the [Export(typeof(iConnector)] in the main plugin, the subplugin is activated, but I want my main plugin to be able to be called in the same manner.
Being new to MEF I am stuck as to how to solve this. Any help would be much appreciated!
You should use Contracts and specify your intent, otherwise MEF will go into an infinite loop or pick the Connector as it exposes IConnector itself.
Some more info from MSDN.
For example
[Export("Container", typeof(IConnector))]
public class Connector : IConnector
{
[Import("Component", typeof(IConnector))]
private IConnector connector;
....
UPDATE
So after giving it some thought, here is an example of metadata based approach, and one that also limits the number of expensive catalog operations.
The IConnector
using System.Xml.Linq;
namespace Common
{
public interface IConnector
{
XDocument Run(object serviceCredentials, object connectorIds, object connectorKeys);
void Identify();
}
}
The metadata attribute ConnectorMetadata
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace Common
{
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class)]
public class ConnectorMetadata : ExportAttribute
{
public string Name { get; private set; }
public ConnectorMetadata(string name):base(typeof(IConnector))
{
Name = name;
}
public ConnectorMetadata(IDictionary<string, object> metaData) : base(typeof (IConnector))
{
Name = Convert.ToString(metaData["Name"]);
}
}
}
The lazy singleton for PluginsCatalog
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;
using Common;
namespace Common
{
public class PluginsCatalog
{
[ImportMany]
public Lazy<IConnector, ConnectorMetadata>[] Connectors;
private static readonly Lazy<PluginsCatalog> LazyInstance = new Lazy<PluginsCatalog>(() => new PluginsCatalog());
private PluginsCatalog()
{
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory();
var directoryCatalog = new DirectoryCatalog(path, "*plugin.dll");
var aggregateCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog);
var container = new CompositionContainer(aggregateCatalog);
container.SatisfyImportsOnce(this);
}
public static PluginsCatalog Instance { get { return LazyInstance.Value; } }
public IConnector GetConnector(string name)
{
var match = Connectors.SingleOrDefault(s => s.Metadata.Name.Equals(name));
return match == null ? null : match.Value;
}
}
}
The "Primary" IConnector
using System;
using System.Xml.Linq;
using Common;
namespace Common
{
[ConnectorMetadata("Primary")]
public class Connector : IConnector
{
public XDocument Run(object serviceCredentials, object connectorIds, object connectorKeys)
{
PluginsCatalog.Instance.GetConnector("Sub").Identify();
return default(XDocument);
}
public void Identify()
{
Console.WriteLine(GetType().FullName);
}
}
}
The "Sub" IConnector
using System;
using System.Xml.Linq;
using Common;
namespace SubPlugin
{
[ConnectorMetadata("Sub")]
public class SubConnector:IConnector
{
public XDocument Run(object serviceCredentials, object connectorIds, object connectorKeys)
{
return default(XDocument);
}
public void Identify()
{
Console.WriteLine(GetType().FullName);
}
}
}
and finally the program itself:
namespace SOMEF
{
class Program
{
static void Main(string[] args)
{
var connector = PluginsCatalog.Instance.GetConnector("Primary");
connector.Identify();
connector.Run(null, null, null);
}
}
}
Which prints:
SOMEF.Connector
SubPlugin.SubConnector
Hope this helps ... :)
You might want to read this https://msdn.microsoft.com/en-us/library/ee155691(v=vs.110).aspx
With exmplanation how named exports are used
public class MyClass
{
[Import("MajorRevision")]
public int MajorRevision { get; set; }
}
public class MyExportClass
{
[Export("MajorRevision")] //This one will match.
public int MajorRevision = 4;
[Export("MinorRevision")]
public int MinorRevision = 16;
}
I'm trying to create a simple index, which includes two fields from my document: TraceRowID, LoadDate.
So I've created the following class:
using Model;
using Raven.Abstractions.Indexing;
using Raven.Client.Indexes;
using Raven.Client.Linq;
using Raven.Client.Document;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Indexes
{
public class IDLoadDateIndex : AbstractIndexCreationTask<ServiceTrace>
{
public IDLoadDateIndex()
{
Map = serviceTrace => from st in serviceTrace
select new { ID = st.TraceRowID, LoadDate = st.LoadDate };
}
}
}
My model is "ServiceTrace":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class ServiceTrace
{
public int TraceRowID { get; set; }
public string StatusDescription { get; set; }
public string FullExceptionText { get; set; }
public string LoadDate { get; set; }
}
}
And there goes my DAL:
using Indexes;
using Raven.Client.Indexes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DAL
{
public class DbConnection
{
private readonly static DbConnection instance = new DbConnection();
private Raven.Client.Document.DocumentStore documentStore;
static DbConnection()
{
}
private DbConnection()
{
this.documentStore = new Raven.Client.Document.DocumentStore { Url = "http://btadmins:8080/" };
this.documentStore.Initialize();
IndexCreation.CreateIndexes(typeof(IDLoadDateIndex).Assembly, this.documentStore);
}
public static DbConnection Instance
{
get
{
return instance;
}
}
public Raven.Client.Document.DocumentStore DocumentStore
{
get
{
return documentStore;
}
}
}
}
For some reason, when stepping over on debug mode on the "CreateIndexes" line, it is done succesfully. BUT I can't see any indexes added on the RavenDB management studio silverlight app.
What can be the problem ?
Perhaps you are looking in a named database in the studio? By not naming a specific database here, you are creating the index in Raven's system database.
Reference: How can a dynamic be used as a generic?
public void CheckEntity(int entityId, string entityType = null)
{
dynamic AnyObject = Activator.CreateInstance("Assembly","Assembly.Models.DbModels." + entityType).Unwrap();
CheckWithInference(AnyObject, entityId);
}
private static void CheckWithInference<T>(T ignored, int entityId) where T : class
{
Check<T>(entityId);
}
private static void Check<T>(int entityId) where T : class
{
using (var gr = new GenericRepository<T>())
{
}
}
This enters with CheckEntity(16,"Container");. After the first line runs, AnyObject becomes a blank Assembly.Models.DbModels.Container when inspected with the debugger. If var AnyType = AnyObject.GetType(); is used, then AnyType shows as Assembly.Models.DbModels.Container. However, when the call to CheckWithInference(AnyObject, entityId); is made an exception is thrown.
outer: Object reference not set to an instance of an object.
inner: Microsoft.CSharp.RuntimeBinder.SymbolTable.GetOriginalTypeParameterType(Type t) +10
I made a self-contained example here - but it runs without error :(
Note, this is in asp.net mvc 3 c#
HomeController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace InferenceExample.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public void CheckEntity(int entityId, string entityType = null)
{
dynamic AnyObject = Activator.CreateInstance("InferenceExample", "InferenceExample.Models." + entityType).Unwrap();
CheckWithInference(AnyObject, entityId);
}
private static void CheckWithInference<T>(T ignored, int entityId) where T : class
{
Check<T>(entityId);
}
private static void Check<T>(int entityId) where T : class
{
var repo = new List<T>();
}
}
}
Example.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace InferenceExample.Models
{
public class Example
{
public int ExampleId { get; set; }
public string Name { get; set; }
}
}
Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.ActionLink("Start", "CheckEntity", new { entityId = 16, entityType = "Example" })
I am at a loss. Why am getting this exception? I was unable to easily reproduce it. I am not sure what else to include for the example as this is all that the actual code has in it.
The really confusing part is that in the application, when this exception occurs, the action fails. However, upon revisiting the page and trying a second time, there is no exception thrown.
As discussed in C# chat room, the solution here is to bypass dynamic entirely and use reflection to invoke the generic method. Dynamic has some nice features but sometimes causes more trouble than it's worth, especially when it's possible to get the Type object at runtime.
var modelType = Type.GetType("InferenceExample.Models." + entityType + ",InferenceExample");
var checkMethod = typeof(HomeController).GetMethod("CheckWithInference", BindingFlags.NonPublic | BindingFlags.Static);
checkMethod.MakeGenericMethod(modelType).Invoke(null, new object[] { entityId });
Glad to help :)