How do I get the names of methods of other classes, called by a concrete class's public method? - reflection

I have the following class:
public class MyClass
{
private readonly IMyDependency myDependency;
public MyClass (IMyDependency myDependency)
{
this.myDependency = myDependency;
}
public int MethodOne (int a, int b)
{
var c = this.myDependency.DoSomething (a, b);
return (c > 0) ? a : b;
}
}
I want to detect the name of the dependency method call (i.e., the "DoSomething ()" method call made on the injected dependency, in the first statement of the "MethodOne ()" method) as a MethodInfo.
How do I do this?

Related

Java 1.8 overridden equals() not called by Collection removeAll()

on my IDE (eclipse neon) i m running jre 1.8. As you can see in the snippet code below i developed My Custom class overriding the equals method. That s cause i want to use my overridden version when i execute the removeAll method from a Set of my custom class.
Looking inside the jdk source code it's possible to verify that removeAll method uses the contains method which in turn uses the equals method of the Object class.
public class MyClass {
private String connectionID;
public MyClass (){
...
}
#Override
public boolean equals(Object obj) {
if (obj instanceof MyClass ){
if (((MyClass )obj).getConnectionID().equalsIgnoreCase(this.getConnectionID())){
return true;
}
}
return false;
}
...
}
public class MyClassContainer{
private Set<MyClass> classes = new HashSet<>();
public Set<MyClass> getClasses () {
return this.classes ;
}
}
public class Main (){
private void method(MyClassContainer contClass) {
if (true){
Set<MyClass> temp = some valid Set;
temp.removeAll(contClass.getClasses());
}
}
Launching this code i m realizing that the overridden equals method is never called.
What is it wrong?
Thanks
For it to work correctly, you need to override hashCode as well:
#Override
public int hashCode() {
return Objects.hash(getConnectionID());
}

DatabaseException: Found two getters or fields with conflicting case sensitivity

Every time I try to retrieve data from my database, I get
com.google.firebase.database.DatabaseException: Found two getters or fields with conflicting case sensitivity for property: n
for any of my fields that are a single letter. Googling this issue gives 0 results and I can find no case incongruities in my code. I don't know if this is a bug in Firebase or if I have to do something special for any fields with names 1 character long.
Here is the rest of the error report if it makes a difference (the line of my code which it references is a simple
params = dataSnapshot.getValue(Parameters.class);
which works everywhere else:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: osu.gd_prototype, PID: 11345
com.google.firebase.database.DatabaseException: Found two getters or fields with conflicting case sensitivity for property: n
at com.google.android.gms.internal.zzaix$zza.zziw(Unknown Source)
at com.google.android.gms.internal.zzaix$zza.<init>(Unknown Source)
at com.google.android.gms.internal.zzaix.zzj(Unknown Source)
at com.google.android.gms.internal.zzaix.zzd(Unknown Source)
at com.google.android.gms.internal.zzaix.zzb(Unknown Source)
at com.google.android.gms.internal.zzaix.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at osu.gd_prototype.DataSend$1.onDataChange(DataSend.java:107)
at com.google.android.gms.internal.zzafp.zza(Unknown Source)
at com.google.android.gms.internal.zzagp.zzSu(Unknown Source)
at com.google.android.gms.internal.zzags$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Here is the code for parameters with the relevant offending getters and setters of the fields which throw the error:
public class Parameters {
public int K;
public double L;
public int D;
public int N;
public Parameters() {
}
public double getL(){
return L;
}
public void setL(double lVal){
L = lVal;
}
public int getK(){
return K;
}
public void setK(int kVal){
K = kVal;
}
public int getD(){
return D;
}
public void setD(int dVal){
D = dVal;
}
public int getN(){
return N;
}
public void setN(int nVal){
N = nVal;
}
}
The Firebase Database consider these items when serializing/deserializing JSON:
public fields
JavaBean-like property getters/setters
Since you have both a public field N and getN()/setN() methods, it considers the two in conflict. While in this case setting N and calling setN() leads to the same result, that may not always be the case. The chance of getting it wrong is too big, which is why the scenario is simply not allowed.
The error message is a bit of a red herring in this case. We should improve that.
Convert the following fields from public to private
public int K;
public double L;
public int D;
public int N;
to
private int K;
private double L;
private int D;
private int N;
I found a different solution to keep my field public String id and at the same time have the method public String getId() which I needed to implement because of an interface: Simply mark the method with #Exclude, e.g.:
public class Group implements Identifiable<String>
{
public String id;
protected Group ()
{
}
public Group ( String id )
{
this.id = id;
}
#Exclude
#Override
public String getId ()
{
return id;
}
}

SQLite Connection - Injection

I'm trying to create a solution with separated classes, so I have:
public class RepositorioPadrao<TEntidade> : IRepositorioPadrao<TEntidade>
where TEntidade : class
{
public readonly ISQLiteConnection _connection;
public RepositorioPadrao(ISQLiteConnectionFactory factory)
{
_connection = factory.Create("easybudget.sql");
_connection.CreateTable<TEntidade>();
}
public virtual void Inserir(TEntidade objeto)
{
_connection.Insert(objeto);
}
Then to use this I have:
public class RepositorioDeCategoria : RepositorioPadrao<Categoria>, IRepositorioDeCategoria
{
public List<Categoria> ObterTudo()
{
return _connection
.Table<Categoria>()
.OrderByDescending(x => x.Descricao)
.ToList();
}
}
The problem is, that EasyBudget.Core.Repositorio.RepositorioPadrao<EasyBudget.Core.Dominio.Categoria> does not contain a constructor that takes 0 arguments.
To solve your current problem, you could add a constructor to RepositorioDeCategoria that calls the base class:
public RepositorioDeCategoria(ISQLiteConnectionFactory factory)
: base(factory)
{
}
Alternatively, if you were going to have several Categoria and you wanted them to share the same _connection, then you might want to reorganise your classes so that they use some form of aggregration instead of inheritance.

MSUnity - Registering Types - Generic Abstract Class

I've just implemented the Translator pattern discussed here and here like so...
ITranslator interface...
public interface ITranslator
{
bool CanTranslate(Type targetType, Type sourceType);
bool CanTranslate<TTarget, TSource>();
object Translate(Type targetType, object source);
TTarget Translate<TTarget>(object source);
}
Translator.cs...
public abstract class Translator<TBusinessEntity, TServiceEntity> : ITranslator where TBusinessEntity : class
where TServiceEntity : class
{
public bool CanTranslate(Type targetType, Type sourceType)
{
return (targetType == typeof(TBusinessEntity) && sourceType == typeof(TServiceEntity)) ||
(targetType == typeof(TServiceEntity) && sourceType == typeof(TBusinessEntity));
}
public bool CanTranslate<TTarget, TSource>()
{
return CanTranslate(typeof (TTarget), typeof (TSource));
}
public TTarget Translate<TTarget>(object source)
{
return (TTarget)Translate(typeof(TTarget), source);
}
public object Translate(Type targetType, object source)
{
if (targetType == typeof(TBusinessEntity))
return ServiceToBusiness((TServiceEntity)source);
if (targetType == typeof(TServiceEntity))
return BusinessToService((TBusinessEntity)source);
throw new System.ArgumentException("Invalid type passed to Translator", "targetType");
}
protected abstract TServiceEntity BusinessToService(TBusinessEntity value);
protected abstract TBusinessEntity ServiceToBusiness(TServiceEntity value);
protected abstract List<TServiceEntity> BusinessToService(List<TBusinessEntity> valueList);
protected abstract List<TBusinessEntity> ServiceToBusiness(List<TServiceEntity> valueList);
}
Here is my StudentFeeTranslator class that implements the Translator abstract methods...
public class StudentFeeTranslator : Translator<StudentFee, StudentFeeType>
{
#region Overrides of Translator<StudentFee,StudentFeeType>
protected override StudentFeeType BusinessToService(StudentFee value)
{
return new
StudentFeeType
{
StudentFeeId = value.StudentFeeRefId,
FeeId = value.FeeRefId,
StudentId = value.StudentRefId,
SchoolId = value.SchoolRefId,
FeeDate = value.AssessmentDate,
FeeAmount = value.AssessmentAmount,
Balance = value.UnpaidBalance,
FeeTypeId = value.FeeType,
Description = value.FeeDescription
};
}
protected override StudentFee ServiceToBusiness(StudentFeeType value)
{
return new
StudentFee
{
StudentFeeRefId = value.StudentFeeId,
FeeRefId = value.FeeId,
StudentRefId = value.StudentId,
SchoolRefId = value.SchoolId,
AssessmentDate = value.FeeDate,
AssessmentAmount = value.FeeAmount,
UnpaidBalance = value.Balance,
FeeType = (Byte)value.FeeTypeId,
FeeDescription = value.Description
};
}
protected override List<StudentFeeType> BusinessToService(List<StudentFee> valueList)
{
return valueList.Select(BusinessToService).ToList();
}
protected override List<StudentFee> ServiceToBusiness(List<StudentFeeType> valueList)
{
return valueList.Select(ServiceToBusiness).ToList();
}
#endregion
}
Next is my StudentFeeService class minus the irrelevant methods. Notice the Translator property tagged for injection...
public partial class StudentFeeService : IStudentFeeService
{
#region Public Members
[Dependency]
public ITranslator Translator { get; set; }
#endregion
#region Private Methods
private List<StudentFeeType> ConvertStudentFeeListToListOfStudentFeeTypes(List<StudentFee> studentFees)
{
return Translator.Translate<List<StudentFeeType>>(studentFees);
}
#endregion
}
Finally, here is the code snippet of my attempt to register the Translator class with my Unity container...
container.RegisterType(typeof (ITranslator), typeof (Translator<,>));
This attempt failed. My question is how can I register a generic abstract class with a Unity container? FYI I'm using MSUnity 2.0.
You are trying to map a non-generic interface to an open generic type. How should Unity (or any other container) guess if your service needs a StudenFeeTranslator or a RentalFeeTranslator? Both implement ITranslator and that is all the container can see.
You can register all of your concrete implementations of ITranslator giving them individual names. This is something all containers support. And then make Unity inject that specific dependency into the Translator property of your service. Something like
container.RegisterType(typeof(ITranslator), typeof(StudentFeeTranslator), "StudentFee");
container.RegisterType(typeof(ITranslator), typeof(RentalFeeTranslator), "RentalFee");
container.RegisterType(typeof(IStudentFeeService), typeof(StudentFeeService),
new InjectionProperty("Translator", new ResolvedParameter<ITranslator>("StudentFee")));
That is a lot of repetetive code though.
Unity does not come with registration conventions out-of-the-box. But the TecX project contains an enhanced configuration engine that would allow you to do something like this:
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(
scanner =>
{
scanner.AddAllImplementationsOf(typeof(ITranslator);
scanner.AssembliesFromApplicationBaseDirectory();
});
container.AddExtension(builder);
This registers all implementations of ITranslator with the name of the implementing class (e.g. the name for StudentFeeTranslator would be StudentFeeTranslator) in one go.
If you make your interface generic it would be easier to inject into the property. Matching ITranslator<X, Y> to an implementation thereof is not really hard to do.

Grails bind request parameters to enum

My Grails application has a large number of enums that look like this:
public enum Rating {
BEST("be"), GOOD("go"), AVERAGE("av"), BAD("ba"), WORST("wo")
final String id
private RateType(String id) {
this.id = id
}
static public RateType getEnumFromId(String value) {
values().find {it.id == value }
}
}
If I have a command object such as this:
class MyCommand {
Rating rating
}
I would like to (for example) automatically convert a request parameter with value "wo" to Rating.WORST.
The procedure for defining custom converters is described here (in the context of converting Strings to Dates). Although this procedure works fine, I don't want to have to create a class implementing PropertyEditorSupport for each of my enums. Is there a better alternative?
I found a solution I'm pretty happy with.
Step 1: Create an implementation of PropertyEditorSupport to convert text to/from the relevant Enum
public class EnumEditor extends PropertyEditorSupport {
private Class<? extends Enum<?>> clazz
public EnumEditor(Class<? extends Enum<?>> clazz) {
this.clazz = clazz
}
public String getAsText() {
return value?.id
}
public void setAsText(String text) {
value = clazz.getEnumFromId(text)
}
}
Step 2: Define a class that registers EnumEditor as a converter for the various enum classes. To change the list of enum classes that are bindable by id, just modify BINDABLE_ENUMS
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
private static final String REQUIRED_METHOD_NAME = 'getEnumFromId'
// Add any enums that you want to bind to by ID into this list
private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2]
public void registerCustomEditors(PropertyEditorRegistry registry) {
BINDABLE_ENUMS.each {enumClass ->
registerEnum(registry, enumClass)
}
}
/**
* Register an enum to be bound by ID from a request parameter
* #param registry Registry of types eligible for data binding
* #param enumClass Class of the enum
*/
private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) {
boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method ->
method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1
}
if (!hasRequiredMethod) {
throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray())
}
registry.registerCustomEditor(enumClass, new EnumEditor(enumClass))
}
}
Step 3: Make Spring aware of the registry above by defining the following Spring bean in grails-app/conf/spring/resources.grooovy
customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
So the default Databinding binds on the Enum name and not a separately defined property of the Enum. You can either create your own PropertyEditor as you have mentioned or do a work-around similar to this:
class MyCommand {
String ratingId
Rating getRating() {
return Rating.getEnumFromId(this.ratingId)
}
static constraints = {
ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null })
}
}

Resources