It can be done but you'll need to jump through a few hoops to make it work.
First of all, a bit of background:
- LinkField does not inherit from the Field class like some other field types do.
- LinkField inherits from XmlField which in turn inherits from CustomField.
- CustomField (and it's subtypes) are instantiated by passing a field instance into the constructor.
- Linkfields store their values in this field instance.
- Linkfields cannot be added to a FieldCollection as they do not inherit from Field.
- Rather than add the LinkField we need to add the LinkField's InnerField property.
- When a Field is pulled from a FieldCollection and assigned to a LinkField an implicit conversion operation is performed.
- The implicit conversion operation creates a new LinkField by passing the selected field to the LinkField's constructor. It is this new LinkField that is returned.
Now some code:
const string externalUrl = "External Url";
const string targetItemName = "Target Item";
Field field = new ShimField { IDGet = () => ID.NewID, NameGet = () => externalUrl };
Item targetitem = new ShimItem { IDGet = () => ID.NewID, NameGet = () => targetItemName };
LinkField linkfield = new ShimLinkField(field) { IsInternalGet = () => true, TargetItemGet = () => targetitem };
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
FieldCollection fields = new ShimFieldCollection { ItemGetString = (name) => linkfield.InnerField };
Item item = new ShimItem { NameGet = () => "Test Item", FieldsGet = () => fields };
And now for a bit of explanation:
The key to making the above code work is the line:
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
By Shimming the implicit conversion operator, we can ensure that when the following line is called:
LinkField linkField = item.Fields["External Url"];
A link field is returned and it's properties are shimmed as you want them.