1

I am (or, shortly, will have been) using AutoMapper to map a bunch of business objects to a bunch of WCF DTOs. It seemed like a decent trick--there was a fair amount of troubleshooting to do at the .CreateMap level, but it overall felt worth it. Until I decided to hide my business logic from outside the assembly.

The BOs and the mapper live in the same project; they spin off external-assembly DTOs, which are public (and would need to be to get through the channel anyway). There is no need to expose the BOs, as the DTOs now do that job, so I thought I'd reset their accessors to internal. Kaboom goes automapping. To illustrate:

(code from BLL, same as AutoMapping)

public class TestObject
{
    private int _myID;
    public int MyID
    {
        get { return _myID; }
        set { _myID = value; }
    }
}

(code from service layer)

public class TestObjectDTO
{
    private int _myID;
    public int MyID
    {
        get { return _myID; }
        set { _myID = value; }
    }
}

this will work

Mapper.CreateMap<TestObject, TestObjectDTO>();

until I do this:

internal class TestObject
...

or even just this, in TestObject:

internal int MyID

Can anyone explain this to me? I'll stop short of calling it a "bug", but it certainly seems to contradict the entire purpose of reflection-based mapping, i.e. to allow objects of different purposes to scale together fluently. Why can't AM handle the mapping, and let me control the accessors?

downwitch
  • 1,362
  • 3
  • 19
  • 40
  • 1
    Because just as many people ask to not support anything but public accessors as do that ask to support all accessors. I think a config option is in order, no? – Jimmy Bogard May 28 '12 at 03:02
  • Cool, would you mind adding a github issue for this? Just to make sure I don't lose it. Thanks! – Jimmy Bogard Jun 06 '12 at 09:23
  • 1
    This is (finally) done https://github.com/AutoMapper/AutoMapper/issues/218 If you will answer the question once it's implemented I'll be able to close the thread. Thanks for the follow-through. – downwitch Jun 15 '12 at 02:49

2 Answers2

0

This is By Design. A couple of options are either using your own resolver which will work with those (private, protected, internal, etc) or mapping to an interface and using explicit interface implementations.

Both approaches are covered by the answers to this previous SO thread:

How can I use AutoMapper on properties marked Internal?

Community
  • 1
  • 1
James Manning
  • 13,429
  • 2
  • 40
  • 64
  • 1
    I had read that thread, quite thoroughly, before posting this. I don't see how implementing an interface (yet another object, yet another layer) is in any way efficient, nor thoroughly explained there, and implementing my own resolver = not automapping. So I posted this in hopes of something better. – downwitch May 27 '12 at 22:42
-1

From MSDN

The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly

IE, anything marked as internal can only be accessed by the code in your project - which means referenced assemblies such as AutoMapper cannot even see things marked as internal. Reflection based mappings require a public class, and public get / set properties.

hawkke
  • 4,242
  • 1
  • 27
  • 23
  • Yes I figured it had something to do with the limitations of reflection. But if I am explicitly passing an object from inside an assembly to the mapper, what does it see? Nothing at all? It's internal, right? – downwitch May 27 '12 at 22:44
  • Correct - it just can't see the internal members. Anything inside your assembly is invisible to everything outside your assembly unless you mark it as public (or protected, as long as you inherit from a protected member). Even with reflection, I believe it can only reflect public or protected members from outside the assembly. - But then again, I've never tried reflecting an internal or private member from another assembly so I can't say for 100% certainty that there isn't a workaround somewhere. – hawkke May 28 '12 at 21:42
  • Hmm from Jimmy's comment above, something tells me this is not the true culprit though. Also, I was asking specifically about an internal *class*--if you pass that to AM, within the same assembly, what does AM see? Nothing? I'm not sure dependency-injection and external-reflection are the same... – downwitch May 29 '12 at 01:22
  • 1
    Internal (and private) members can be accessed with reflection. @pat-p's hack in this [question](http://stackoverflow.com/q/3208057/1811525) shows how. (Focus on `BindingFlags.NonPublic`.) – CodeFox Apr 25 '16 at 06:01