0

I have the following interface:

 public interface ISearchProperties {
    string CurrentUserLocation { get; set; }
    string SearchUsername { get; set; }
 }

With the following implementations:

public class BroadcastPreviewDto : ISearchProperties {
    // other properties
}
public class ProfileSearchDto : ISearchProperties {
    // other properties
}

I have the following functions:

public void PrepSearchProperties(ProfileSearchDto query) {
    // do a bunch of stuff to query properties here (only on ISearchProperties properties)
}
public void PrepSearchProperties(BroadCastPreviewDto query) {
    // do a bunch of same stuff to query properties here (only on ISearchProperties properties)
}

The problem is that this isn't very DRY - the function bodies are exactly the same thing. I tried doing this:

public void PrepSearchProperties(ISearchProperties query) {
    // do a bunch of stuff to query properties here
}

But this doesn't quite work unless I declare the original query as ISearchProperties, which strips the implementing class properties.

What pattern can I follow to DRY my code up?

RobVious
  • 12,685
  • 25
  • 99
  • 181
  • 1
    Is there a reason you absolutely have to use `ref`? -- Why not just have a method `public void PrepSearchProperties(ISearchProperties query)`? – Corak Aug 12 '16 at 03:40
  • @Corak if I return an `ISearchProperties` object from `Prep` then I have to convert `ISearchProperties` to whatever concrete type I'm passing in - isn't this bad? – RobVious Aug 12 '16 at 03:46
  • 1
    You don't have to return anything. You don't need the `ref` unless you're actually assigning a new value to `query`. Are you? I suspect maybe you don't quite understand what `ref` does - or you do, but there's relevant code missing from your example. – Blorgbeard Aug 12 '16 at 03:51
  • 1
    So you create a new object inside these methods? Then how about a method `private void PrepSearchPropertiesImpl(ISearchProperties query)` where you handle all the stuff that really only needs an `ISearchProperties` object, and call this from the other methods like: `public void PrepSearchProperties(ref ProfileSearchDto query) { query = new ProfileSearchDto(); PrepSearchPropertiesImpl(query); }`? – Corak Aug 12 '16 at 03:51
  • @Blorgbeard yes `query` properties are being modified on the object - I'm passing the reference in intentionally but am open to returning a new object. – RobVious Aug 12 '16 at 03:53
  • 2
    If you're only modifying *properties*, you do not need `ref`. No need for `ref` in this code: `query.xyz = "foobar";`. You would only need `ref` if you're doing `query = new ProfileSearchDto();`. – Blorgbeard Aug 12 '16 at 03:54
  • 1
    See: http://stackoverflow.com/questions/8708632/passing-objects-by-reference-or-value-in-c-sharp/8708674#8708674 – Blorgbeard Aug 12 '16 at 03:58
  • @Blorgbeard - noted! Thanks for that. Though I'm still stuck with the above - whether or not I use `ref`, I need to pass in an implementation of an interface and retain the implementing class properties, know what I mean? – RobVious Aug 12 '16 at 04:02
  • 1
    If you lose the `ref` from your final code snippet, you can pass any implementation of `ISearchProperties` to it: you can pass either a `ProfileSearchDto` or a `BroadCastPreviewDto`, or whatever - and when the function returns, it will still be whatever it was before - just with its `ISearchProperties` properties changed. – Blorgbeard Aug 12 '16 at 04:04

1 Answers1

2

If you have this function definition:

public void PrepSearchProperties(ISearchProperties query) {
    // statements of the form:
    query.SearchProperty = 123;
}

Then you can pass any implementation of ISearchProperties to it. Example:

public class BroadcastPreviewDto : ISearchProperties {
    // implement ISearchProperties here
    // more, implementation-specific properties, e.g.
    public string BroadcastType { get; set; }
}

var bp = new BroadcastPreviewDto() {
    // set implementation specific properties here
    BroadcastType = "example"
};

// this compiles and executes fine
PrepSearchProperties(bp);

// Same instance as before. No properties stripped.
Console.WriteLine(bp.BroadcastType);  
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272