Hi
I have a little application that does datavalidation.
It supports dynamically loaded plugins (you drop a dll with a class
implementing IValidator<Tin the same dir as the main application).
All classes that implement this interface are shown in a drop down in
a DataGridViewComboBoxColumn named Validator.
By choosing the class to validate this specific data in the drop
downbox IValidator<T>.Validate is called and returns true/false. Which
in turn alerts the users. (The data can be any kind of audio data,
image data, text data ...)
DataGridViewComboBoxColumn validatorColumn =
dragDropDataGridView1.Columns["Validator"] as
DataGridViewComboBoxColumn;
if (validatorColumn != null)
{
validatorColumn.DisplayMember = "Name";
validatorColumn.ValueMember = "IValidator<string>.Name"; // this line
fails
}
It also fails like this
validatorColumn.ValueMember = "Name";
Error is cannot convert to string. I have a ToString() implemented in
the actual validator implementation.
Actual IValidator<Timplementation
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using TMData.Data.Validation;
using System.Text.RegularExpressions;
namespace Validators
{
// Dummy implementation to show concept
class EmailValidator : IValidator<string>
{
#region IValidator<stringMembers
string IValidator<string>.Name
{
get
{
return GetType().ToString();
}
}
string IValidator<string>.Error
{
get
{
return "The data does not have the correct format for
an email";
}
}
bool IValidator<string>.Validate(string data)
{
if (data == string.Empty) return true;
Regex re = new Regex(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]
{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|
[0-9]{1,3})(\]?)$");
if (re.IsMatch(data))
return (true);
else
return (false);
}
// This does not work
string IValidator<string>.ToString()
{
return ((IValidator<string>)this).Name;
}
// This does not work
public string ToString()
{
return ((IValidator<string>)this).Name;
}
// This does not work
public overrride string ToString()
{
return ((IValidator<string>)this).Name;
}
#endregion
}
}
However if I make the interface implementation implicit it works (like
this)
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using TMData.Data.Validation;
using System.Text.RegularExpressions;
namespace Validators
{
class EmailValidator : IValidator<string>
{
#region IValidator<stringMembers
public string Name
{
get
{
return GetType().ToString();
}
}
public string Error
{
get
{
return "The data does not have the correct format for
an email";
}
}
public bool Validate(string data)
{
if (data == string.Empty) return true;
Regex re = new Regex(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]
{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|
[0-9]{1,3})(\]?)$");
if (re.IsMatch(data))
return (true);
else
return (false);
}
public override string ToString()
{
return Name;
}
#endregion
}
}
Why?
I prefer to work with explicit interfaces to encourage separation like
this since it is not all developers that does interface based
programming you can force them by using explicit interface
implementation.
ISomeInterface obj = new SomeObject();
instead of
SomeObject obj = new SomeObject();
Maybe it has some thing to do with that I instantiate the objects like
this.
(In form load)
DirectoryInfo dirInfo = new
DirectoryInfo(Path.GetDirectoryName(Assembly.GetEn tryAssembly().Location));
Array.ForEach<FileInfo>(dirInfo.GetFiles("*.dll"),
delegate(FileInfo fileInfo)
{
Array.ForEach<Type>(Assembly.LoadFile(fileInfo.Ful lName).GetTypes(),
delegate(Type type)
{
if (type.IsClass &&
(type.GetInterface("IValidator`1") != null))
{
validators.Add((IValidator<string>)Activator.Creat eInstance(type));
}
}
);
}
);
I have tried using the generic Activator.CreateInstance<Tbut I could
not get it to work properly.
Regards
Ken