Executing a method on a class via a generic interface

P

Peter Morris

Hi all

Is there any way I can remove the non-generic IView interface and work only
with IView<T>? The PassReferences method will only receive a System.Object
instance so I wont know the type of the object I need a view for until
runtime. I'd really like to be able to remove the non-generic IView
interface so that anything implementing IView<T> doesn't also need a weakly
typed method which simply typecasts and passes onto the IView<T> interface's
method.

Thanks


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication17
{
public interface IView
{
void DoSomething(object viewObject);
}

public interface IView<T> : IView
{
void DoSomething(T viewObject);
}

public class PersonDto
{
public string Name { get; set; }
}

public class PersonDtoView : IView<PersonDto>
{
public void DoSomething(object viewObject)
{
var personDto = (PersonDto)viewObject;
DoSomething(personDto);
}

public void DoSomething(PersonDto viewObject)
{
Console.WriteLine(viewObject.Name);
}
}


class Program
{
static void Main(string[] args)
{
var personDto = new PersonDto();
personDto.Name = "Peter Morris";

var view = new PersonDtoView();
view.DoSomething(personDto);

PassReferences(personDto);
}

static void PassReferences(object viewObject)
{
//Determine the view type
Type viewTypeRequired = typeof(IView<>).MakeGenericType(new Type[] {
viewObject.GetType() });

//Use some mechanism to get the implementor for the required view type
//not relevant here so I will hard code it, would be something like:
//Type viewTypeImplementor = ViewTypeImplementors[viewTypeRequired];
Type viewTypeImplementor = typeof(PersonDtoView);

//Create an instance of the view implementor
var view = (IView)Activator.CreateInstance(viewTypeImplementor);

//Execute the view
view.DoSomething(viewObject);
}
}
}
 
P

Peter Morris

Here's the actual code

public void UpdateBusinessObjects(IEcoServiceProvider ecoServiceProvider,
ILoopBack context, TemplateDto source)
{
//01: Find the current person
//02: Update the person's properties
//03: Do not update the DB, that's an app layer's job
Template result = new Template();
result.Name = source.Name;
foreach (var dtoProperty in source.Properties)
TranslateProperty(ecoServiceProvider, result, dtoProperty);
}

private void TranslateProperty<T>(IEcoServiceProvider ecoServiceProvider,
Template template, T propertyDto)
where T : TemplatePropertyDto
{
//Find the translater
Type translaterType = typeof(IDtoTranslater<T>);
IDtoTranslater<T> dtoTranslater =
(IDtoTranslater<T>)Container.Resolve(translaterType);

//Find the property
TemplateProperty templateProperty =
template.GetPropertyByName(propertyDto.Name);

dtoTranslater.UpdateBusinessObjects(ecoServiceProvider, templateProperty,
propertyDto);
}


source.Properties is a List<TemplatePropertyDto>. This means that the <T>
in TranslateProperty is always TemplatePropertyDto and not the actual type
of the instance in the list. TemplatePropertyDto is an abstract class so
that's no good to me.

Is there any way I can either get the <T> in TranslateProperty to be the
instance type, or a way to implement TranslaterProperty without needing to
pass <T>?


Thanks
 
P

Pavel Minaev

  private void TranslateProperty<T>(IEcoServiceProvider ecoServiceProvider,
Template template, T propertyDto)
   where T : TemplatePropertyDto
  {
   //Find the translater
   Type translaterType = typeof(IDtoTranslater<T>);
   IDtoTranslater<T> dtoTranslater =
(IDtoTranslater<T>)Container.Resolve(translaterType);

   //Find the property
   TemplateProperty templateProperty =
template.GetPropertyByName(propertyDto.Name);

   dtoTranslater.UpdateBusinessObjects(ecoServiceProvider, templateProperty,
propertyDto);
  }

source.Properties is a List<TemplatePropertyDto>.  This means that the <T>
in TranslateProperty is always TemplatePropertyDto and not the actual type
of the instance in the list.  TemplatePropertyDto is an abstract class so
that's no good to me.

Is there any way I can either get the <T> in TranslateProperty to be the
instance type, or a way to implement TranslaterProperty without needing to
pass <T>?

You're essentially trying to do virtual/dynamic dispatch here on the
argument which is not a method receiver. To the best of my knowledge,
the only choice here is reflection (i.e. the call to TranslateProperty
should be done with reflection, using the actual type of the object
for T). Coincidentially, that's one case where C# 4.0 "dynamic" will
come in handy...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top