ECO and custom services
As you are well aware, ECO is heavily modularized by use of services.
You have surely noticed that when getting an eco service with code similar to
-
var ocl = ServiceProvider.GetEcoService<IOclService>();
As things have matured, the DefaultEcoSpace now implements simple properties for the more common built-in services;
-
// Summary:
-
// The IVariableFactoryService of the EcoSpace
-
//
-
// Remarks:
-
// The IVariableFactoryService contains methods for creating free standing ECO
-
// elements that can be used as variables. The elements returned will implement
-
// IElement, and any other applicable interfaces from the Eco.ObjectRepresentation
-
// namespace. This propery is equivalent to retieving the IVariableFactoryService
-
// from an IEcoServiceProvider using GetEcoService(typeof(IVariableFactoryService)).
-
public IVariableFactoryService VariableFactory { get; }
-
//
-
// Summary:
-
// The IVersionService of the EcoSpace
-
//
-
// Remarks:
-
// The IVersionService is used for accessing historical values of ECO objects.
-
// This propery is equivalent to retieving the IVersionService from an IEcoServiceProvider
-
// using GetEcoService(typeof(IVersionService)).
-
public IVersionService Versioning { get; }
and quite a few more.
What is not obvious at first glance is that anyone can register a service by means of the method DefaultEcoSpace.RegisterEcoService(Type type, object instance). As with any other service, the services you register are available from any service provider in which they are registered.
Here’s an idea I probably got from Peter Morris; add your own ICurrentUserService.
The idea is to have a globally available service that can tell you who – if anyone – is logged in.
My suggestion for an interface looks like:
-
public interface IUserService<T>
-
{
-
bool Login(string userName, string password);
-
void Logout();
-
T CurrentUser { get; }
-
bool IsLoggedIn { get; }
-
}
The reason for a generic interface is to avoid linking it to the specific model.
The implementation is fairly straight forward. Note that there is a hard coded OCL expression that may or may not be suitable for you. It’s easy to change that to be set by a parameter. One of those famous exercises for the reader.
-
public class CurrentUserService<T>: IUserService<T>
-
{
-
private IEcoServiceProvider ServiceProvider { get; set; }
-
public CurrentUserService (IEcoServiceProvider serviceProvider)
-
{
-
ServiceProvider = serviceProvider;
-
}
-
public bool Login(string userName, string password)
-
{
-
var variables = ServiceProvider.GetEcoService<IVariableFactoryService>().CreateVariableList("var_username", userName);
-
variables.AddConstant("var_password", password);
-
-
var ocl = ServiceProvider.GetEcoService<IOclService>();
-
IList<T> users = ocl.Evaluate("User.AllInstances->select((username = var_username) and (password = var_password))->First", variables).GetAsIList<T>();
-
if (users.Count == 1)
-
{
-
currentUser = users[0];
-
return true;
-
}
-
return false;
-
}
-
-
public void Logout()
-
{
-
currentUser = default(T);
-
}
-
private T currentUser;
-
public T CurrentUser
-
{
-
get
-
{
-
if (IsLoggedIn)
-
return currentUser;
-
return default(T);
-
}
-
}
-
public bool IsLoggedIn
-
{
-
get { return ServiceProvider != null && currentUser != null; }
-
}
-
}
Add this to the pool of services in the constructor of your ecospace
-
public EcoProject1EcoSpace(): base()
-
{
-
InitializeComponent();
-
this.RegisterEcoService(typeof(IUserService<User>), new CurrentUserService<User>(this));
-
}
Make it a first class citizen by adding a property for it
-
public IUserService UserService { get { return GetEcoService<IUserService<User>>(); } }
After that, you can login, check for current user and what you may need.
Here’s the OK event on my login form
-
private void btnOk_Click(object sender, EventArgs e)
-
{
-
var userService = EcoSpace.GetEcoService<IUserService<User>>();
-
if (!userService.Login(tbxUsername.Text, tbxPassword.Text))
-
{
-
DialogResult = DialogResult.None;
-
MessageBox.Show("Invalid user name or password.");
-
}
-
}
I use the logged in state to block some menus on the application;
-
private void mnuFile_DropDownOpening(object sender, EventArgs e)
-
{
-
mnuLogin.Enabled = !EcoSpace.UserService.IsLoggedIn;
-
mnuLogout.Enabled = EcoSpace.UserService.IsLoggedIn;
-
mnuChangePassword.Enabled = EcoSpace.UserService.IsLoggedIn;
-
}
Some objects need to relate to the current user. Add that to the Created method of the class
-
public partial class SomeModeledClass
-
{
-
partial void Created()
-
{
-
CreatedByUser = AsIObject().ServiceProvider.GetEcoService<IUserService<User>>().CurrentUser;
-
CreatedDate = DateTime.Now;
-
}
-
}
There are many a neat things that can be plugged in as services. I hope this gives you an idea of what is possible.
–Jesper Hogstrom
Cool!
Thank you for the example!
Hello Jesper,
Could you please answer how can I use instead of in the the constructor of my ecospace when I am registering my custom service?
Sorry for the stupid question,
Thank you,
Regards,
Alex
“T” instead of the “User”
I am afraid I don’t quite understand what kind of information you want. Please rephrase and I’ll try to help.
@Guest
You can override the Active property of the EcoSpace.